I have been using Cypress to test my code. And as it turns out, the content-header is no longer present when I run the app on Chrome controlled by Cypress. The response content length is needed for the proper functioning of my software, which uses the values to do some computations. I was wondering if there's some way in which I get content-length for writing my tests. The part of my test code where this occurs is as follows:
cy.get('#setSelectedComponent').click().then(() => {
cy.contains('Part C').click()
cy.get('#createInstanceFromAsmTree').click({ force: true })
cy.get(`[aria-label="Toggle Assembly D"]`).click({ force: true })
cy.get('#matTreeNode').contains('Part C-1').should('be.visible')
})
The 'cy.contains('Part C').click()' is where a response is received wherein the content-header is needed.
You will have to check the Network tab for what request(s) are sent when you click on 'Part C', then spy on those with cy.intercept() to check the request header.
cy.get('#setSelectedComponent').click()
cy.intercept('url-to-intercept').as('url')
cy.contains('Part C').click()
cy.wait('#url')
// get the 'Content-Length' header in request
.its('request.headers["Content-Length"]')
Related
I'm learning how SvelteKit works. There is a pretty nice "hello world PLUS" place to start with the "create-svelte" example. In that example there is a "todos" page. Source files here. It's a simple page where you can add an delete things to do tasks. And I'm trying to figure out how the individual tasks are managed.
I can see where an todos array is created in Javascript on the client; I can verify that via console.logs in index.svelte file. I can see via Chrome Inspect (dev tools, network tab) where the creation of a task generates a todos.json network Post request http://localhost:3000/todos.json The get/post request simply returns the original content back to the client.
What I'm not seeing is where the data is being stored on the browser. I was fully expecting to see something in local storage, session storage, cookies or even indexeddb.
What I'm not seeing is where that content is being stored. If I close the browser tab and reopen, the data is there. If I open a different browser on the same local computer, no task data exists. If I "empty cache and hard reload" the task data remains.
After doing some testing, I can see one cookie.
Name: userid Value: d38b9b44-1a8b-414e-9a85-1c2b2c0700f4 Domain: localhost Path: / Expires/MaxAge: Session Size: 42 HttpOnly: ✓ Priority: Medium
If I modify or delete this cookie in any way then the stored task data disappears.
So where is the todos task data being temporarily stored? What am I not seeing?
I read the header for this file _api.js multiple times. I tested "https://api.svelte.dev" in the browser and got back null responses.. I just assumed that this was a dead server.
It turns out that the folks at svelte do offer a fully functional api server, both receiving, deleting and storing todo task data. See my test notes within api function.
A browser request to https://api.svelte.dev/todos/d38b9b44-1a8b-414e-9a85-1c2b2c0700f4 absolutely returns my task data, and now I can see how this stuff works. Info offered here in case anybody else is wondering what's going on here.
Here is the complete _api.js file
/*
This module is used by the /todos.json and /todos/[uid].json
endpoints to make calls to api.svelte.dev, which stores todos
for each user. The leading underscore indicates that this is
a private module, _not_ an endpoint — visiting /todos/_api
will net you a 404 response.
(The data on the todo app will expire periodically; no
guarantees are made. Don't use it to organise your life.)
*/
const base = 'https://api.svelte.dev';
export async function api(request, resource, data) {
console.log("resource: ", resource);
// returns--> resource: todos/d38b9b44-1a8b-414e-9a85-1c2b2c0700f4
//https://api.svelte.dev/todos/d38b9b44-1a8b-414e-9a85-1c2b2c0700f4 <--- test this !!
// user must have a cookie set
if (!request.locals.userid) {
return { status: 401 };
}
const res = await fetch(`${base}/${resource}`, {
method: request.method,
headers: {
'content-type': 'application/json'
},
body: data && JSON.stringify(data)
});
// if the request came from a <form> submission, the browser's default
// behaviour is to show the URL corresponding to the form's "action"
// attribute. in those cases, we want to redirect them back to the
// /todos page, rather than showing the response
if (res.ok && request.method !== 'GET' && request.headers.accept !== 'application/json') {
return {
status: 303,
headers: {
location: '/todos'
}
};
}
return {
status: res.status,
body: await res.json()
};
}
I'm currently attempting to setup an XMPP client using Stanza.js
https://github.com/legastero/stanza
I have a working server that accepts connections from a Gajim client, however when attempting to connect using Stanza.js client.connect method, the server opens up a websocket connection, but no events for authentication, or session started ever fire.
The server logs do not show any plaintext password authentication attempts.
How can I actually see any of the stanza logs to debug this issue?
import * as XMPP from 'stanza';
const config = { credentials: {jid: '[jid]', password: '[password]'}, transports: {websocket: '[socketurl]', bosh: false} };
const client = XMPP.createClient(config)
client.on('raw:*', (data) => {
console.log('data', data)
})
client.connect();
onconnect event does fire, but this is the only event that fires.
Is there a way to manually trigger authentication that isn't expressed in the documentation?
The raw event handler should be able to give you the logging you want - but in your code sample, you are invoking it incorrectly. Try the following.
client.on('raw:*', (direction, data) => {
console.log(direction, data)
})
For reference, the docs state that the callback for the raw data event handler is
(direction: incoming | outgoing, data: string) => void
So the data that you are looking for is in the second argument, but your callback only has one argument (just the direction string "incoming" or "outgoing", although you have named the argument "data").
Once you fix the logging I expect you will see the stream immediately terminates with a stream error. Your config is incorrect. The jid and password should be top level fields. Review the stanza sample code. For the options to createClient - there is no credentials object. Try the following:
const config = { jid: '[jid]', password: '[password]', transports: {websocket: '[socketurl]', bosh: false} };
Since your username and password are hidden behind an incorrect credentials object, stanza.io does not see them and you are effectively trying to connect with no username and password so no authentication is even attempted.
This issue happened to be caused by a configuration problem.
The jabber server was using plain authentication.
Adding an additional line to the client definition file helped.
Also adding
client.on('*', console.log)
offered more complete server logs.
client.sasl.disable('X-OAUTH2')
How can I actually see any of the stanza logs to debug this issue?
If the connection is not encrypted, you can sniff the XMPP traffic with tools like
sudo tcpflow -i lo -Cg port 5222
You can force ejabberd to not allow encryption, so your clients don't use that, and you can read the network traffic.
Alternatively, in ejabbed.yml you can set this, but probably it will generate a lot of log messages:
loglevel: debug
I have a suite of end-to-end Cypress tests for my web app. When the tests run, AJAX calls are made against a real server (i.e. the requests are not mocked or stubbed). Currently, I do something like the following to ensure that the tests wait for these AJAX requests to complete
// declare the AJAX request we will wait for
cy.route('POST', '/api/authenticate').as('authenticate')
// type the username and password and click the login button
cy.get('#username').type('john-doe')
cy.get('#password').type('secret')
cy.get('#login-button').click()
// wait for the AJAX request to complete before testing the response code
cy.wait('#authenticate')
cy.get('#authenticate').then(xhr => {
expect(xhr.status).to.eq(200)
})
This seems very verbose, is there a simpler way? I'm using the latest version of Cypress, v. 6.1.0.
cy.server() and cy.route() are deprecated in Cypress 6.0.0. Instead cypress introduced cy.intercept(). So you can write something like:
// declare the AJAX request we will wait for
cy.intercept('POST', '/api/authenticate').as('authenticate')
// type the username and password and click the login button
cy.get('#username').type('john-doe')
cy.get('#password').type('password')
cy.get('#login-button').click()
// wait till we get 200
cy.wait('#authenticate').its('response.statusCode').should('eq', 200)
//You can also assert request body and response body contents
cy.wait('#authenticate').its('request.body').should('include', 'username')
cy.wait('#authenticate').its('response.body').should('include', 'password')
In the example here, it's written like this.
cy.wait('#authenticate').should('have.property', 'status', 200)
Not a huge saving, but it's something :)
Edit:
I just noticed you saying you have the latest version. I'd follow Alapan's suggestion in that case.
I'm developing a webapp using ReactJS for the frontend and express for the backend. I'm deploying my app to azure.
To test if my requests are going through I wrote two different API requests.
The first one is very simple:
router.get('/test', (req, res) => {
res.send('test was a success');
});
Then in the frontend I have a button which when clicked makes the request and I get the response 'test was a success'. This works every time.
The second test is:
router.post('/test-email', (req, res) => {
let current_template = 'reset';
readHTMLFile(__dirname + '/emails/' + current_template + '.html', function(err, html) {
let htmlSend;
let template = handlebars.compile(html);
let = replacements = {
name: req.body.name
};
htmlSend = template(replacements);
let mailOptions = {
from: 'email#email.com',
to: 'someone#email.com',
subject: 'Test Email',
html: htmlSend
};
transporter.sendMail(mailOptions)
.then(response => {
res.send(response);
})
.catch(console.error);
});
});
Then when I've deployed the app I make a call to each one of these tests. The first one, like I mentioned always succeeds. The second one which is supposed to send a very simple email fails most of the time with the error "iisnode encountered an error when processing the request. HRESULT: 0x6d HTTP status: 500 HTTP subStatus: 1013". The strange thing is that every once in a while the email will send but this happens very rarely. Most times the request will take exactly two minutes before sending a response with an error.
I should note that when in development in localhost both tests work all the time with no issues whatsoever, it's only when in production (deployment to azure) that this happens.
I've been digging around for the last few days and came up with nothing. Any help or directions would be greatly appreciated.
I found out what the problem was. I'm using gmail to send my test emails, by default gmail will block any attempts to use an account if it thinks the app making the request is not secure. This can be easily fixed by simply clicking the link they automatically send you when you make your first attempt. What is not immediately obvious is when you go in production mode they add another level of security which in this case I believe is a captcha, and while you'll be able to send emails in development as soon as you deploy your app this no longer becomes the case.
Anyway, after digging around a little more I found the option to disable the captcha and now my emails send fine!
Link to that option https://accounts.google.com/b/0/DisplayUnlockCaptcha
Hopefully this will help someone.
I have been working on a simple production management process based around smartsheet. The code that I have been running has been working fine on my Ubuntu machine, then I copied it over to my Parrot Linux machine running the same node version and it won't find a row that exists. Below is the request:
var copyRow = {
"rowIds": artToProdRowsToCopy,
"to": {
"sheetId": productionId
}
};
// Set options
var options = {
sheetId: artId,
body: copyRow,
queryParameters: {
include: "all"
}
};
console.log(options);
// Copy the normal engraved rows from art to production
smartsheet.sheets.copyRowToAnotherSheet(options)
.then(function(results) {
callback1(null, results);
})
.catch(function(error) {
console.log(error);
});
The log output of options:
{ sheetId: 8129017524546436,
body:
{ rowIds: [ 8886954296800644 ],
to: { sheetId: 6941481487333252 } },
queryParameters: { include: 'all' } }
The error:
{ statusCode: 404,
errorCode: 1006,
message: 'Not Found',
refId: 'zjl2z56296l9' }
I'm running node v8.9.1, on Parrot Linux 3.9.
I've checked that each of these sheet and row ID #'s are correct and they all are (the ones in the examples are not real however). Any help would be appreciated.
Edit: Adding debug info:
[Smartsheet] 2017-11-20T20:22:55.876Z[ INFO] POST https://api.smartsheet.com/2.0/sheets/8129017124546436/rows//copy?include=all
[Smartsheet] 2017-11-20T20:22:55.876Z[VERBOSE] Request Payload (preview): {"rowIds":[2759271070885764,3212501789763460,4576920289470340,8982631438149508,2962733838690180,8886959296800644],"to":{"sheetId":6941441487333252}}
[Smartsheet] 2017-11-20T20:22:55.876Z[ DEBUG] Request Payload (full): {"rowIds":[2759271070885764,3212501789763460,4576920289470340,8982631438149508,2962733838690180,8886959296800644],"to":{"sheetId":6941441487333252}}
[Smartsheet] 2017-11-20T20:22:56.155Z[ ERROR] Request failed after 0 retries
[Smartsheet] 2017-11-20T20:22:56.156Z[ ERROR] POST https://api.smartsheet.com/2.0/sheets/8129017124546436/rows//copy?include=all
[Smartsheet] 2017-11-20T20:22:56.156Z[ ERROR] Response: Failure (HTTP 404)
Error Code: 1006 - Not Found
Ref ID: 85bn0m2j8oki
I don't see any obvious issues with your request structure. Typically, the 404 Not Found error is related to an issue with the request URI, rather than the contents of the request itself. i.e., a 404 Not Found error means that, for some reason or another, the request URI is not reachable.
The URI for the Copy Row(s) request is:
POST /sheets/{sheetId}/rows/copy
A few troubleshooting suggestions:
Verify that the casing of all characters in the request URI are lowercase.
Verify that the sheet corresponding to the sheetId value in the request URI exists.
Verify that the user who owns the API Access token that you're specifying in the Authorization header of the Copy Row(s) API request does indeed have access to the sheet corresponding to the sheetId value in the request URI.
As described in the Troubleshooting section of the API docs, I'd suggest that you use a tool like Fiddler or Charles HTTP Proxy to examine the raw HTTP request that your app is sending, then you can investigate/verify the items I've listed above.
Update #1
Thanks for updating your post with debugging info. Based on that, it looks like your request URI contains an extra slash between the words rows and copy:
POST https://api.smartsheet.com/2.0/sheets/8129017124546436/rows//copy?include=all
Perhaps this is causing your problem?
Update #2
I've been able to reproduce the Not Found error in Postman if my Request URI contains two slashes between the words rows and copy(like your debug output shows). Removing one of these slashes fixes the issue. That is, your request should look like this (only one slash between the words rows and copy).
POST https://api.smartsheet.com/2.0/sheets/8129017124546436/rows/copy?include=all
Looks like our SDK bug. Stay tuned for a fix.
Fixed in version 1.0.3 - now on Github and npm.
https://www.npmjs.com/package/smartsheet
https://github.com/smartsheet-platform/smartsheet-javascript-sdk/releases/tag/v1.0.3