NSURLRequest isEqual: affected by allHTTPHeaderFields - foundation

I compare two NSURLRequest objects which URL and header are same, but isEqual: return NO, so debug:
when I po [taskRequest isEqual:request] result is NO, po request.allHTTPHeaderFields to check is equal, then po [taskRequest isEqual:request] result is YES🤔️
I found if use addValue:forHTTPHeaderField: instead of setValue:forHTTPHeaderField:, it always return YES
I try verify in playground Xcode Version 10.2 (10E125):
let request1 = NSMutableURLRequest(url: URL(string: "https://api.abc.com")!)
let request2 = NSMutableURLRequest(url: URL(string: "https://api.abc.com")!)
request1.setValue("1", forHTTPHeaderField: "1")
request2.setValue("1", forHTTPHeaderField: "1")
request1 == request2 // true
request2.allHTTPHeaderFields // ["1": "1"]
request1 == request2 // false
I expect isEqual: result always correct no matter if I have used the allHTTPHeaderFields method

Related

How to get the Id of this response and then serialize it?

I need to get the id from a response with a for loop, then make a call and serialize the final result but I don't know how. This is the code:
Http http = new Http();
HTTPResponse response;
HttpRequest request;
String userEmail = 'myemail#mail.com';
request = new HttpRequest();
request.setMethod('GET');
request.setEndpoint('callout:Gmail_API/gmail/v1/users/myemail#mail.com/messages?q=from:anothermail#mail.com');
response = http.send(request);
System.debug(response.getBody());
If I run an "Execute anonymous apex" I get this:
{
"messages": [
{
"id": "17d9fdeb824b97be",
"threadId": "17d9fdeb824b97be"
}
],
"resultSizeEstimate": 1
}
And essentially I need to return that response and get the Id and then make a call with the threadId and serialize it in a list which I have to use it in a Salesforce lightning component later. How do I do that? Thank you in advance.
Please use the below code snippet to get the threadId value.
if(response.getStatusCode() == 200) {
JSONParser parser = JSON.createParser(response.getBody());
while (parser.nextToken() != null) {
if (
(parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
(parser.getText() == 'threadId')
) {
parser.nextToken();
threadId = parser.getText();
}
}
}
If it helps you, please mark it as the best answer to help others as well.

how to write this test in playwright: if element text as int is > 0 test pass else test fail

I am trying to see if a number being displayed on a page is greater than 0 or not.
If it is I need the test to pass
if not I need the test to fail
The code I have so far
test("searching for 0100t should show a out of pocket expense", async()=>{
let surgicalCentersCost = await page.$$eval('.chart-inner-label-cost >> nth=0')
let hospitalOutpatientCost = await page.$$eval('.chart-inner-label-cost >> nth=1')
surgicalCentersCost = surgicalCentersCost.replace('$','');
hospitalOutpatientCost = hospitalOutpatientCost.replace('$','');
surgicalCentersCost = parseInt(surgicalCentersCost);
hospitalOutpatientCost = parseInt(hospitalOutpatientCost)
expect(surgicalCentersCost) // <-- what happens here?
})
essentially Id like an if statement that looks at surgicalCentersCost and hospitalOutpatientCost and if both are > 0 signal test pass otherwise signal test fail
I know we can do things like this in cypress but the company I am working for insits on playwright. Is such a thing possible?
Im about to test this but it looks like regex is the way to go. Observe the last 2 lines.
test("searching for 0100t should show a out of pocket expense", async()=>{
let surgicalCentersCost = await page.$$eval('.chart-inner-label-cost >> nth=0')
let hospitalOutpatientCost = await page.$$eval('.chart-inner-label-cost >> nth=1')
surgicalCentersCost = surgicalCentersCost.replace('$','');
hospitalOutpatientCost = hospitalOutpatientCost.replace('$','');
surgicalCentersCost = surgicalCentersCost.replace(',','');
hospitalOutpatientCost = hospitalOutpatientCost.replace(',','');
surgicalCentersCost = parseInt(surgicalCentersCost);
hospitalOutpatientCost = parseInt(hospitalOutpatientCost)
await expect(surgicalCentersCost).toHaveValue(/^[1-9][0-9]*$/)
await expect(hospitalOutpatientCost).toHaveValue(/^[1-9][0-9]*$/)
})

Fail to send multiuser email

Case: i would like to Blind Copy TO multiuser [send mail]
method 1: using vector [Fail] with error message say is null
var maildoc:NotesDocument = database.createDocument();
maildoc.replaceItemValue("Form", "Memo");
maildoc.replaceItemValue("Subject", "STATUS OF APPLICATION FOR REQUEST AN EMAIL");
session.setConvertMime(false);
var z:java.util.Vector = new java.util.Vector();
var vw:NotesView = database.getView("(Notifier Setting)");
var doc:NotesDocument = vw.getFirstDocument();
if (doc != null) {
z.addElement(doc.getItemValue("HRM"));
z.addElement(doc.getItemValue("GM"));
}
maildoc.replaceItemValue("BlindCopyTo",z)
method 2: using array [Fail] with error message replaceitemvalue cannot used array
var z=[];
var vw:NotesView = database.getView("(Notifier Setting)");
var doc:NotesDocument = vw.getFirstDocument();
if (doc != null) {
z.push(doc.getItemValue("HRM"));
z.push(doc.getItemValue("GM"));
}
maildoc.replaceItemValue("BlindCopyTo",z)
method 3:Using string [no person in blindcopy list]
maildoc.replaceItemValue("BlindCopyTo",doc.getItemValue("HRM")+","+doc.getItemValue("GM"))
May i know which way is correct way?
The function NotesDocument.getItemValue() returns a (java.util.)Vector, so if you use addElement or push on z (as in methods 1 and 2), it just adds the whole vector instead of its children.
Your code should work if you use method 1 and replace
z.addElement(doc.getItemValue("HRM"));
z.addElement(doc.getItemValue("GM"));
with
z.addAll(doc.getItemValue("HRM"));
z.addAll(doc.getItemValue("GM"));
PS: Mark Leusink has written a nice SSJS class for mail sending which is available in OpenNTF XSnippets.

How to get the reply message without the original message from the Gmail API

I would like to get the reply message in a thread without the original message. However, when I use either Users.messages: GET or Users.threads: GET, I receive the reply (as desired) with the original message (undesired) as well. See screenshot below code.
(This question, as far as I can tell, was also posed here, however I did not find that the proposed solution answers the question and the poster of the proposed solution suggested I start a new question. I tried with Users.threads as Tholle suggests however received the same result.)
I'm a noob, so any and all help is greatly appreciated and I apologize if I'm missing something obvious.
Code
var gapiGETRequest = function (gapiRequestURL)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", gapiRequestURL, false );
xmlHttp.send( null );
return xmlHttp.responseText;
}
var gapiRequestInboxMessagesAndToken = "https://www.googleapis.com/gmail/v1/users/me/messages?q=-label%3ASENT+in%3AINBOX&access_token=" + thisToken
var allMessagesReceived = gapiGETRequest(gapiRequestInboxMessagesAndToken)
var allMessagesObject = JSON.parse(allMessagesReceived)
var messageIdsOfReceivedMessages = [];
var getIdsOfReceivedMessages = function(responseObject){
for(var i=0; i < responseObject.messages.length; i ++) {
messageIdsOfReceivedMessages.push(responseObject.messages[i].id);
}
}
var messageContentsArr = [];
var getMessageContents = function(messageIdList)
{
for(var i=0; i < messageIdList.length; i++)
{
var gapiRequestMessageWithId = "https://www.googleapis.com/gmail/v1/users/me/messages/" + messageIdList[i] + "?access_token=" + thisToken
var currentMessage = JSON.parse(gapiGETRequest(gapiRequestMessageWithId))
var encodedMessageContents = currentMessage.payload.parts[0].body.data
var decodedMessageContents = atob(encodedMessageContents.replace(/-/g, '+').replace(/_/g, '/'));
messageContentsArr.push(decodedMessageContents)
}
}
getIdsOfReceivedMessages(allMessagesObject);
getMessageContents(messageIdsOfReceivedMessages);
Response
You are getting the full reply message. When the report replied, they quoted the original message and this the text of the original is in the reply message. You may just want to do what Gmail and many other modern emails apps do and collapse/hide any reply text which begins with >.
This is my solution. It's a bit long but I tried to document it as detailed as possible.
Handles message returned by Gmail API:
https://developers.google.com/gmail/api/v1/reference/users/messages#resource
Input:
Hello. This is my reply to message.
On Thu, Apr 30, 2020 at 8:29 PM John Doe <john.doe#example.com>
wrote:
> Hey. This is my message.
>
--
John Doe
My Awesome Signature
Output:
Hello. This is my reply to message.
Code: (Unfortunately this has no syntax highlight :P)
const message = await getMessageFromGmailApi();
const text = getGoogleMessageText(message);
console.log(text, '<= AWESOME RESULT');
function getGoogleMessageText(message) {
let text = '';
const fromEmail = getGoogleMessageEmailFromHeader('From', message);
const toEmail = getGoogleMessageEmailFromHeader('To', message);
let part;
if (message.payload.parts) {
part = message.payload.parts.find((part) => part.mimeType === 'text/plain');
}
let encodedText;
if (message.payload.parts && part && part.body.data) {
encodedText = part.body.data;
} else if (message.payload.body.data) {
encodedText = message.payload.body.data;
}
if (encodedText) {
const buff = new Buffer(encodedText, 'base64');
text = buff.toString('ascii');
}
// NOTE: We need to remove history of email.
// History starts with line (example): 'On Thu, Apr 30, 2020 at 8:29 PM John Doe <john.doe#example.com> wrote:'
//
// We also don't know who wrote the last message in history, so we use the email that
// we meet first: 'fromEmail' and 'toEmail'
const fromEmailWithArrows = `<${fromEmail}>`;
const toEmailWithArrows = `<${toEmail}>`;
// NOTE: Check if email has history
const isEmailWithHistory = (!!fromEmail && text.indexOf(fromEmailWithArrows) > -1) || (!!toEmail && text.indexOf(toEmailWithArrows) > -1);
if (isEmailWithHistory) {
// NOTE: First history email with arrows
const historyEmailWithArrows = this.findFirstSubstring(fromEmailWithArrows, toEmailWithArrows, text);
// NOTE: Remove everything after `<${fromEmail}>`
text = text.substring(0, text.indexOf(historyEmailWithArrows) + historyEmailWithArrows.length);
// NOTE: Remove line that contains `<${fromEmail}>`
const fromRegExp = new RegExp(`^.*${historyEmailWithArrows}.*$`, 'mg');
text = text.replace(fromRegExp, '');
}
text = text.trim()
return text;
}
function getGoogleMessageEmailFromHeader(headerName, message) {
const header = message.payload.headers.find((header) => header.name === headerName);
if (!header) {
return null;
}
const headerValue = header.value; // John Doe <john.doe#example.com>
const email = headerValue.substring(
headerValue.lastIndexOf('<') + 1,
headerValue.lastIndexOf('>')
);
return email; // john.doe#example.com
}
function findFirstSubstring(a, b, str) {
if (str.indexOf(a) === -1) return b;
if (str.indexOf(b) === -1) return a;
return (str.indexOf(a) < str.indexOf(b))
? a
: b; // NOTE: (str.indexOf(b) < str.indexOf(a))
}
Substring the reply content alone, based on your Email id position in the full email string.
$str = "VGhhbmtzIGZvciB0aGUgbWFpbC4NCg0KT24gVHVlLCBKdWwgMTIsIDIwMjIgYXQgMjo1OCBQTSA8aW5mb0BhaXJjb25uZWN0aW5kaWEuY29tPiB3cm90ZToNCg0KPiBTLk5vIFZlbmRvciBQcm9kdWN0IEJhbmR3aWR0aCBGcm9tIExvY2F0aW9uIFRvIExvY2F0aW9uDQo-IDEgQWlydGVsIEludGVybmV0IDEwMCAyMS4xNzAyNDAxLDcyLjgzMTA2MDcwMDAwMDAxDQo-IDE5LjA0NjE5NTY4NjA2MjMxMiw3Mi44MjAyNzY0Mzc4MjA0Mw0KPg0K";
$str_raw = strtr($str, array('+' => '-', '/' => '_'));
$full_email = utf8_decode(base64_decode($str_raw));
$split_position = strpos($full_email, "your_mail_id") - 33; //33 - before that some date time available, remove those also
$final_string = substr($full_email, 0, $split_position);
echo $final_string;
Let me save your day
console.log(message.split("On")[0])
output : Hello. This is my reply to message.

Splitting url parameter node.js?

I am having the following url parameter
sample value actual value contains so many parameters
var data = "browserName=MSIE&cookies=Rgn=%7CCode%3DMUMBAI%7Ctext%3DMumbai%7C; NREUM=s=1376355292394&r=220970&p=2080092;cs_uuid=209712058942163; cs_si=209712058942163.1&javascriptEnabled=true";
Following function is used to get the particular parameter
//Generic Function to get particular parameter
getParameterValue : function(data, parameter) {
var value = null;
if (data.length > 0) {
var paramArray = data.split("&");
for ( var i = 0; len = paramArray.length, i < len; i++) {
var param = paramArray[i];
var splitter = parameter + "=";
if (param.indexOf(splitter) > -1) {
value = param.substring(param.indexOf(splitter)
+ splitter.length, param.length);
break;
}
}
}
return value;
}
Example
getParameterValue(data, "browserName");
output is MSIE //correct
Problem is
getParameterValue(data, "cookies");
Output is
Rgn=%7CCode%3DMUMBAI%7Ctext%3DMumbai%7C; NREUM=s=1376355292394
But required output is
Rgn=%7CCode%3DMUMBAI%7Ctext%3DMumbai%7C; NREUM=s=1376355292394&r=220970&p=2080092;cs_uuid=209712058942163; cs_si=209712058942163.1
To Know :
1.URL parameter is encoded(clientside) while sending to node server and decoded.
2.NREUM is not encoded, So getParameterValue method splits upto 1376355292394.
Any help to improve getParameterValue function.
Ready to explain more.
Well, getParameterValue() does seem to be parsing data correctly, but data is not encoded properly to distinguish between delimiters and value characters.
The value of cookies, for example:
cookies=Rgn=%7CCode%3DMUMBAI%7Ctext%3DMumbai%7C; NREUM=s=1376355292394&r=220970&p=2080092;cs_uuid=209712058942163; cs_si=209712058942163.1
Should itself be encoded (on top of any encoding used for the cookie values themselves).
cookies=Rgn%3D%257CCode%253DMUMBAI%257Ctext%253DMumbai%257C%3B%20NREUM%3Ds%3D1376355292394%26r%3D220970%26p%3D2080092%3Bcs_uuid%3D209712058942163%3B%20cs_si%3D209712058942163.1
And, it's rather late to try to "fix" this server-side because of the ambiguity. It'll need to be encoded client-side, which can be done with encodeURIComponent().
'cookies=' + encodeURIComponent(cookies)
If you happen to be using jQuery, you can use jQuery.param() to help ensure proper encoding.
var data = {
browserName: 'MSIE',
cookies: document.cookie,
javascriptEnabled: true
};
data = $.param(data); // browserName=MSIE&cookies=Rgn%3D%257CCode...
Or, you can use a light-weight recreation, at least for the "traditional" format.
function urlParam(params) {
var res = [];
for (var name in params) {
res.push(encodeURIComponent(name) + '=' + encodeURIComponent(params[name]));
}
return res.join('&');
}
var data = urlParam(data);
Example: http://jsfiddle.net/GQpTB/
Also, are you aware that Node.js has querystring.parse()?
// with: var qs = require('querystring');
var query = qs.parse(data);
console.log(query.cookies); // ...

Resources