Can't use extensions with GraphQLError - exception

From the Apollo Graphql document, this way can define extension error:
https://www.apollographql.com/docs/apollo-server/data/errors/
import { GraphQLError } from 'graphql';
throw new GraphQLError('the error message',
extensions: {
code: 'SOMETHING_BAD_HAPPENED',
http: {
status: 404,
headers: new Map([
['some-header', 'it was bad'],
['another-header', 'seriously'],
]),
},
},
);
But in my case it got this error:
Argument of type '{ extensions: { code: string; http: { status: number; headers: Map<string, string>; }; }; }' is not assignable to parameter of type 'Maybe<ASTNode | readonly ASTNode[]>'.
Object literal may only specify known properties, and 'extensions' does not exist in type 'ASTNode | readonly ASTNode[]'.
23 extensions: {
~~~~~~~~~~~~~
24 code: 'SOMETHING_BAD_HAPPENED',
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
31 },
~~~~~~~~~~~~
32 },
~~~~~~~~~
Found 1 error(s).
I'm using these packages:
"apollo-server-core": "^3.7.0",
"apollo-server-express": "^3.4.0",
"apollo-server-plugin-base": "^0.13.0",
I also tried to install apollo-server-testing but still can't use extensions.

You forgot to encapsulate the second argument with an object. { extensions }
Do this:
throw new GraphQLError('the error message',
{ // curly bracket here to open the object
extensions: {
code: 'SOMETHING_BAD_HAPPENED',
http: {
status: 404,
headers: new Map([
['some-header', 'it was bad'],
['another-header', 'seriously'],
]),
},
},
} // curly bracket here to close the object
);
Also, #Alpin Cleopatra answer works because of the constructor overload, but it's not intended to be used this way.
See the two signatures here:

This way works:
throw new GraphQLError('the error message',
null,
null,
null,
null,
null,
{
code: 'SOMETHING_BAD_HAPPENED',
http: {
status: 404,
},
},
);

Related

How to use React Testing Library to test for appearance/disappearance of elements in Gutenberg editor using Puppeteer?

I have the following set up:
E2E Test Utils - standard WP Gutenberg e2e testing set that uses Jest and Puppeteer
testing-library/pptr-testing-library - All your favorite user-centric querying functions from #testing-library/react & #testing-library/library available from Puppeteer!
I'm having a problem testing for appearance and disappearance of elements in the GB editor. I'm now aware that extended assertions don't work with Puppeteer. I just can't figure out what to test for. When I run the test in an interactive mode, I can see that everything is going fine, but I don't get the correct result. The result of the query is just an empty object. Here's a snippet of my code:
import {
enablePageDialogAccept,
setBrowserViewport,
createNewPost,
openDocumentSettingsSidebar,
insertBlock,
loginUser,
} from '#wordpress/e2e-test-utils';
import '#testing-library/jest-dom/extend-expect';
import { getDocument, queries, waitFor } from 'pptr-testing-library';
import { clearPuppeteerBrowser } from '../../../lib/helpers/e2eHelpers';
const {
getByRole,
getByLabelText,
getByDisplayValue,
getByText,
queryByLabelText,
findByRole,
findByLabelText,
findByText,
findAllByText,
} = queries;
describe('CVGB Button block', () => {
// Initialize vars within suite's scope
let $document;
let $editorSettings;
let $editorContent;
// Enable page dialog before running any tests
beforeAll(async () => {
await clearPuppeteerBrowser();
await loginUser();
await enablePageDialogAccept();
});
// Wait for creating a new post before running each of the tests
beforeEach(async () => {
await createNewPost();
$document = await getDocument(page);
// we want to look for Sidebar region only
$editorSettings = await getByRole($document, 'region', { name: 'Editor settings' });
// the same for the editor content, so we don't get repeated components from all the document
$editorContent = await getByRole($document, 'region', { name: 'Editor content' });
});
it('should be able to unset a Link when URL is already set', async () => {
await insertBlock('CVGB Button');
await openDocumentSettingsSidebar();
const $linkButton = await findByRole($document, 'button', {
name: 'Link',
});
await $linkButton.click();
const $URLInput = await findByRole($document, 'combobox', {
name: 'URL',
});
await $URLInput.click();
await $URLInput.type('https://www.google.es');
await $URLInput.press('Enter');
await waitFor(() => {
expect(
findByLabelText($document, 'Currently selected', {
exact: false,
})
).toBeInTheDocument();
});
});
});
Here is the error I see:
The complete Node error message below the test reads:
(node:41767) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.
at /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:208:63
at new Promise (<anonymous>)
at CDPSession.send (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:207:16)
at ExecutionContext._evaluateInternal (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/ExecutionContext.js:200:50)
at ExecutionContext.evaluateHandle (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/ExecutionContext.js:151:21)
at /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/pptr-testing-library/lib/index.ts:101:8
at Generator.next (<anonymous>)
at /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/pptr-testing-library/dist/index.js:8:71
at new Promise (<anonymous>)
at Object.<anonymous>.__awaiter (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/pptr-testing-library/dist/index.js:4:12)
(node:41767) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 908)
EDIT: In response to Caleb Eby's asnwer
I thought that's what the waitFor() is for… however if I add only the await findByLabelText(), I get an error:
SyntaxError: /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/blocks/button/test/buttonBlock.e2e.spec.js: Unexpected reserved word 'await'. (126:16)
If I change it to:
await waitFor(async () => {
expect(
await findByLabelText($document, 'Currently selected', {
exact: false,
})
).toBeInTheDocument();
});
It takes a very long time to run the test and ends in error:
expect(received).toBeInTheDocument()
received value must be an HTMLElement or an SVGElement.
Received has type: object
Received has value:
{
"_client": {
"_callbacks": [Map],
"_connection": [Connection],
"_sessionId": "9E13F5776A59D1DD6A177F48A9D1A543",
"_targetType": "page",
"emitter": [Object],
"eventsMap": [Map]
},
"_context": {
"_client": [CDPSession],
"_contextId": 17,
"_world": [DOMWorld]
},
"_disposed": false,
"_frameManager": {
"_client": [CDPSession],
"_contextIdToContext": [Map],
"_frames": [Map],
"_isolatedWorlds": [Set],
"_mainFrame": [Frame],
"_networkManager": [NetworkManager],
"_page": [Page],
"_timeoutSettings": [TimeoutSettings],
"emitter": [Object],
"eventsMap": [Map]
},
"_page": {
"_accessibility": [Accessibility],
"_client": [CDPSession],
"_closed": false,
"_coverage": [Coverage],
"_emulationManager": [EmulationManager],
"_fileChooserInterceptors": [Set],
"_frameManager": [FrameManager],
"_javascriptEnabled": true,
"_keyboard": [Keyboard],
"_mouse": [Mouse],
"_pageBindings": [Map],
"_screenshotTaskQueue": [ScreenshotTaskQueue],
"_target": [Target],
"_timeoutSettings": [TimeoutSettings],
"_touchscreen": [Touchscreen],
"_tracing": [Tracing],
"_viewport": [Object],
"_workers": [Map],
"emitter": [Object],
"eventsMap": [Map]
},
"_remoteObject": {
"className": "HTMLDivElement",
"description": "div.block-editor-link-control__search-item.is-current",
"objectId": "-193265238525024879.17.113",
"subtype": "node",
"type": "object"
}
}
This actually has a possible culprit of a solution, but what is the right way of testing for this (instead of toBeInTheDocument())?
It looks like you are missing an await inside of the expect block, since findByLabelText returns a promise:
expect(
await findByLabelText($document, 'Currently selected', {
exact: false,
})
).toBeInTheDocument();

Nativescript OCR fails with generic error

I am trying to use the nativescript-ocr plugin, and keep on getting this error message
CONSOLE ERROR file:///app/newcard/newcard.component.js:133:34: {
"error": "Recognize failed, check the log for possible details."
}
It is very unhelpful, and i have been stuck on it for too long.
Bellow you can see how i am implementing the ocr:
doRecognize(source: string): void {
console.log({source});
let img: ImageSource = new ImageSource()
img.fromResource(source).then((success: boolean) => {
if (success) {
this.ocr.retrieveText({
image: img,
language: 'eng',
onProgress: (percentage: number ) => {
console.log(`Decoding progress: ${percentage}%`);
}
}).then(
(result: RetrieveTextResult) => {
console.log(`Result: ${result.text}`);
},
(error) => {
})
}
});
}
The source string looks like so:
CONSOLE LOG file:///app/newcard/newcard.component.js:122:20: {
"source":
"file:///Users/georgekyr/Library/Developer/CoreSimulator/Devices/0723299A-7C8B-40C3-AE74- FEE8E08BB52D/data/Media/DCIM/100APPLE/IMG_0007.PNG"
}
Looking around, I find that there are cases wehere the folder app/tesseract/tessadata was created in the wrong way, so i have double checked that the folder exists in the right place with the right data in it.

Dart json.encode is not encoding as needed by Firebase Function

I've been working on this issue for some time now, and I can't seem to figure out what exactly the issue is. In Dart(2) the json.encode() does not seem to be giving me the result I am aiming for.
I am passing in a Map<String, dynamic> that looks like this:
_data = <String, dynamic>{
'uid': newProfileCreationModel.accountID,
'displayName': newProfileCreationModel.profileName,
'greeting': newProfileCreationModel.profileBody ?? '',
'avatarSrc': newProfileCreationModel.avatarSrc,
'heroSrc': newProfileCreationModel.heroSrc,
'accountType': newProfileCreationModel.accountType,
'cityID': newProfileCreationModel.cityID,
'cityName': newProfileCreationModel.cityName,
'country': newProfileCreationModel.countryCode,
'state': newProfileCreationModel.stateAbv,
};
and using this to convert it to JSON
final String _jsonData = json.encode(_data);
Then I am sending it to a google cloud function in the following way.
final Uri _uri = Uri.parse(functionUrl);
final String _jsonData = json.encode(_data);
final String _userToken = await AuthenticationService.getUserToken();
HttpClient client = new HttpClient();
HttpClientRequest request = await client.postUrl(_uri);
request.headers.set('Authorization', 'Bearer ' + _userToken);
request.headers.set('Content-Type', 'application/json; charset=utf-8');
print('Encoded: ' + _jsonData);
request.write(_jsonData);
HttpClientResponse response = await request.close();
if(response.statusCode != HttpStatus.OK){ ...
The line where I print the encoded string outputs this to the console:
05-04 18:52:57.902 26146-26200/com.app.name I/flutter: Encoded: {"uid":'123456789',"displayName":"James","greeting":"My Greetings!","avatarSrc":"http://cdn.free.com/someImage.jpg","heroSrc":"http://cdn.free.com/someImage.jpg","accountType":"per","cityID":1,"cityName":"Eugene","country":"US","state":"OR"}
However the request.write(_jsonData) fails with the following firebase console log error Request Body Missing Data the response that looks like this in the
Firebase Console Log.
Request body is missing data. {
uid: '123456789',
displayName: 'James',
greeting: 'My Greetings!',
avatarSrc: 'http://cdn.free.com/someImage.jpg',
heroSrc: 'http://cdn.free.com/someImage.jpg', accountType: 'per',
cityID: 1,
cityName: 'Eugene',
country: 'US',
state: 'OR'
}
Invalid request IncomingMessage {
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: null,
pipesCount: 0,
flowing: true,
ended: true,
endEmitted: true,
reading: false,
sync: false,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: false,
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
socket:
Socket {
connecting: false,
_hadError: false,
_handle:
TCP {
bytesRead: 13285,
_externalStream: {},
fd: 14,
reading: true,
owner: [Circular],
onread: [Function: onread],
onconnection: null,
writeQueueSize: 0,
_consumed: true },
_parent: null,
_host: null,
The interesting part is that the data is getting through as is clearly displayed in the firebase console log, however it won't recognize it as the body.
Raw Data Approach
When I try sending a raw JSON object through the request.write() as
request.write({'hello':'universe'});
I get a totally different kind of error in the firebase console.
SyntaxError: Unexpected token h in JSON at position 1
at Object.parse (native)
at parse (/var/tmp/worker/node_modules/body-parser/lib/types/json.js:84:17)
at /var/tmp/worker/node_modules/body-parser/lib/read.js:102:18
at IncomingMessage.onEnd (/var/tmp/worker/node_modules/raw-body/index.js:149:7)
at IncomingMessage.g (events.js:292:16)
at emitNone (events.js:86:13)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
on the firebase side I am using a function using a callable, this is where the firebase console logs are being recorded from
export const finalizeProfile = functions.https.onCall((data, context) => {
//CODE
});
Is anyone able to spot what I may be doing incorrectly?
The solution was hidden in plain sight. The issue had to do with a missing field. for Firebase Cloud Functions, the contents 'body', as referred to in the error message body is missing data, literally means it requires a key named data which contains the object of data you are passing.
The google docs are not(ish) crystal clear on this, as they are missing an example https://firebase.google.com/docs/functions/callable-reference#request_body
This is how the data must be sent to functions.https.onCall(), note the Data Field as compared to the original question which did not include this:
{
"data":{
"uid":"123456789",
"displayName":"James",
"greeting":"My Greeting!",
"avatarSrc":"http://cdn.free.com/someImage.jpg",
"heroSrc":"http://cdn.free.com/someImage.jpg",
"accountType":"per",
"cityID":1,
"cityName":"Eugene",
"country":"OR",
"state":"AL"
}
}
The resulting code that now works looks as follows:
// Helper function to format any map to be used for Firebase
Map prepMapForFirebaseJSON(Map<String, dynamic> mapData){
Map<String, Map<String, dynamic>> _fireJson = {
'data' : mapData
};
return _fireJson;
}
// Process HTTP request
final Uri _uri = Uri.parse(functionUrl);
final String _jsonData = json.encode(prepMapForFirebaseJSON(mapData));
final String _userToken = await AuthenticationService.getUserToken();
HttpClient client = new HttpClient();
HttpClientRequest request = await client.postUrl(_uri);
request.headers.set('Authorization', 'Bearer ' + _userToken);
request.headers.set('Content-Type', 'application/json; charset=utf-8');
request.write(_jsonData);
request.close();
I think closing the request is missing:
request.write(_jsonData);
var response = await request.close();

Ember data - Cannot read property 'typeKey' of undefined

Trying to load a plan model, embedded, into my app model.
I keep getting the following error when loading (it saves just fine):
Cannot read property 'typeKey' of undefined TypeError: Cannot read property 'typeKey' of undefined
at Ember.Object.extend.modelFor (http://localhost:4200/assets/vendor.js:71051:22)
at Ember.Object.extend.recordForId (http://localhost:4200/assets/vendor.js:70496:21)
at deserializeRecordId (http://localhost:4200/assets/vendor.js:71500:27)
at http://localhost:4200/assets/vendor.js:71477:11
at http://localhost:4200/assets/vendor.js:69701:20
at http://localhost:4200/assets/vendor.js:17687:20
at Object.OrderedSet.forEach (http://localhost:4200/assets/vendor.js:17530:14)
at Object.Map.forEach (http://localhost:4200/assets/vendor.js:17685:14)
at Function.Model.reopenClass.eachRelationship (http://localhost:4200/assets/vendor.js:69700:42)
at normalizeRelationships (http://localhost:4200/assets/vendor.js:71463:12) vendor.js:17062logToConsole
With that said I have the following models,
app/models/app.js
export default DS.Model.extend({
name: attribute('string'),
domain: attribute('string'),
plan: DS.belongsTo('plan', { embedded: 'load' }),
creator: DS.belongsTo('user', { async: true }),
time_stamp: attribute('string', {
defaultValue: function () {
return moment().format("YYYY/MM/DD HH:mm:ss");
}
})
});
app/models/plan.js
export default DS.Model.extend({
price: attribute('number'),
description: attribute('string'),
tagline: attribute('string'),
title: attribute('string'),
features: attribute('array') // Array is defined in a transform, don't worry.
});
Plan being kind of a static document.
Here's my server response when calling store.get('creator.apps');
{
"apps":[
{
"_id":"53da9994b2878d0000a2e68f",
"name":"Myapp",
"domain":"http://myapp.com",
"creator":"53d9598bb25244e9b1a72e53",
"plan":{
"_id":"53d93c44b760612f9d07c921",
"price":0,
"description":"Free plan",
"tagline":"Great for testing",
"title":"Developer",
"features":["5,000 Requests","API/Plugin Access"],
"__v":0
},
"time_stamp":"2014/07/31 13:31:32",
"__v":0
}
]
}
I realize that the typeKey error is due to Ember not finding a model for the response. I can confirm that it finds the app type, firing a hook under normalizeHash.apps.
Sorry this is such a long post, just can't wrap my head around the cause of the issue!
App.Thing = DS.Model.extend(
{
name: attr('string'),
children: DS.hasMany('child', {inverse:null})
}
);
App.ThingSerializer = DS.RESTSerializer.extend(
DS.EmbeddedRecordsMixin, {
attrs: {
children: { embedded: 'always' }
}
}
);
DS.EmbeddedRecordsMixin must be in your model and you must have `embedded:'always' for the correct attribute.
If you have a Thing model then you can make Ember Data load the embedded children (here and array of nested objects) by using the model specific serializer.
Resources:
http://emberjs.com/guides/models/customizing-adapters/
http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html
Ember doesn't want to have the record embedded in the JSON of the parent record.
Do what you need to, to get your json like this. With just the plan id.
{
"apps":[
{
"_id":"53da9994b2878d0000a2e68f",
"name":"Myapp",
"domain":"http://myapp.com",
"creator":"53d9598bb25244e9b1a72e53",
"plan_id":"53d93c44b760612f9d07c921", // just output id only not embedded record
"time_stamp":"2014/07/31 13:31:32",
"__v":0
}
]
}
This then lets ember look up the related model itself, using the async: true
export default DS.Model.extend({
name: attribute('string'),
domain: attribute('string'),
plan: DS.belongsTo('plan', { async: true }), //changed
creator: DS.belongsTo('user', { async: true }),
time_stamp: attribute('string', {
defaultValue: function () {
return moment().format("YYYY/MM/DD HH:mm:ss");
}
})
});
I've just gone through the pain of this myself and with some help found an answer.
For anyone else who's come here and still is has issues, read my answer to my own question for a detailed rundown of what the typeKey error means and further steps I used to resolve the issue myself.
Deploying ember-rails to Heroku - TypeError: Cannot read property 'typeKey' of undefined

Handling 404 exceptions in Sencha touch Store with an ajax proxy

I'm trying to make my code a little more robust, by handling all sorts of exceptions that may occur. One may be a 404 exception on a Json web request. It looks like the callback method of store.load isn't called when the Json request gets a 404 exception.
The code:
Ext.regModel('Activiteit', {
fields: [
{ name: 'id', type: 'int' },
{ name: 'ServerId', type: 'int', mapping: 'Id' },
{ name: 'Title', type: 'string' },
{ name: 'Description', type: 'string' },
],
});
Ext.regApplication({
name: 'App',
launch: function () {
console.log('launch');
var ajaxActiviteitStore = new Ext.data.Store({
model: "Activiteit",
storeId: 'ajaxActiviteitStore',
proxy: {
type: 'ajax',
url: '/senchatest/Activiteit/Gett/',
reader: {
type: 'json',
root: 'activiteiten'
}
}
});
ajaxActiviteitStore.load(function (records, operation, success) {
//the operation object contains all of the details of the load operation
console.log(success);
});
}
});
This results in a "Uncaught TypeError: Cannot read property 'length' of undefined" exception on line 7212 of sencha-touch-debug.js. I'm using version 1.1.0 of sencha touch.
The stacktrace:
Uncaught TypeError: Cannot read property 'length' of undefined
Ext.data.Store.Ext.extend.loadRecords sencha-touch-debug.js:7212
Ext.data.Store.Ext.extend.onProxyLoad sencha-touch-debug.js:7024
(anonymous function) sencha-touch-debug.js:8742
Ext.data.Connection.Ext.extend.onComplete sencha-touch-debug.js:17566
Ext.data.Connection.Ext.extend.onStateChange sencha-touch-debug.js:17513
(anonymous function) sencha-touch-debug.js:3421
What am I doing wrong here?
I found a workaround by adding a listener to the proxy that listens to the 'exception' event, but I'd rather like the callback function of the store load to be called. Am I doing something wrong, or is this default behaviour?
Thanks,
Sander
I encounter the same Exception (Uncaught TypeError: Cannot read property 'length' of undefined) with an AjaxProxy (ST 1.1.0) if the server return an error (404, 500, ...).
Actually, I think the problem is in the Ext.data.AjaxProxy.createRequestCallback method.
I solved my problem with a dirty code like this:
var ajaxActiviteitStore = new Ext.data.Store({
model: "Activiteit",
storeId: 'ajaxActiviteitStore',
proxy: {
type: 'ajax',
url: 'some nonexistent url',
reader: {
type: 'json',
root: 'activiteiten'
},
listeners: {
exception: function(store, response, op) {
console.log('Exception !');
// hack to avoid js exception :
// TypeError: 'undefined' is not an object (evaluating 'records.length')
// on line sencha-touch-debug-1-1-0.js:7212
op.records = [];
}
}
}
});
Hope this can help, and I will look to open an issue on sencha-touch forum.
I think you have another problem that unexisted url. Nevertheless, try this:
var storeException = 0;
this.ajaxActiviteitStore = new Ext.data.Store({
model: "Activiteit",
storeId: 'ajaxActiviteitStore',
proxy: {
type: 'ajax',
url: 'some nonexistent url',
reader: {
type: 'json',
root: 'activiteiten'
},
listeners: {
exception: {
fn: function(proxy, response, operation ) {
// you can parse `response.responseText` to make some decisions
storeException = 404;
}
}
}
}
});
this.ajaxActiviteitStore.load({
scope: this,
callback: function (records, operation, success) {
if (storeException==0) {
// do something
} else {
alert('Service unaviable');
}
}
});