I'm trying to use express to parse the querystring in case certain parameters are set and execute a little piece of code, before the actual routing is happening. The use-case is to grab a certain value, that could be set, independant of what link is being used. I use express' functionality to pass the stuff to the next possible rule using next().
So far, I tried - at the very top of all the app.get/post-rule-block:
app.get('[?&]something=([^&#]*)', function(req, res, next) {
var somethingID = req.params.something;
// Below line is just there to illustrate that it's working. Actual code will do something real, of course.
console.log("Something: "+somethingID);
next();
})
app.get('/', site.index);
and also:
app.param('something', function(req, res, next) {
var somethingID = req.params.something;
console.log("Something: "+somethingID);
next();
})
app.get('/', site.index);
Example of what should be triggered:
URL: www.example.com/?something=10239
URL: www.example.com/superpage/?something=10239
URL: www.example.com/minisite/?anything=10&something=10239
Unfortunately, none of my solutions actually worked, and all that happens is, that the next matching rule is triggered, but the little function above is never executed. Anybody have an idea, of how this can be done?
EDIT: I do understand, that the param-example wasn't working, as I'm not using said parameter within any other routing-rule afterwards, and it would only be triggered then.
I also do understand, that logic implies, that Express ignores the querystring and it is normally parsed within a function after the routing already happened. But as mentioned, I need this to be "route-agnostic" and work with any of the URL's that are processed within this application.
express does not allow you to route based on query strings. You could add some middleware which performs some operation if the relevant parameter is present;
app.use(function (req, res, next) {
if (req.query.something) {
// Do something; call next() when done.
} else {
next();
}
});
app.get('/someroute', function (req, res, next) {
// Assume your query params have been processed
});
Ok, there is quite a logical flaw in here. Routing only uses the URL, and ignores the querystring.
The (or better "A") solution is actually this:
app.get('*', function(req, res, next) {
if (req.query.something) {
console.log("Something: "+req.query.something);
};
next();
})
Explanation: As Express is ignoring the querystring for the routing, the only regular expression matching all URL's is "*". Once that is triggered, I can check if said querystring is existing, do my logic and continue the routing matching the next rule by using "next()".
And yes: facepalm
Related
I am very new to playwright and i have a problem.
I am trying to implement comparing two screenshots (before and after) in one test.
this is what i want to achieve:
navigate to webpage
take screenshot (before.png)
do some stuff,state changes, etc
take screenshot (after.png)
compare before.png to after.png (if they are the same test should pass, otherwise test fails)
something like this:
test('compare screenshots', async ({ page }) => {
await page.goto('my website here');
const beforeImage = await page.screenshot({
path: `./screenshots/before.png`
})
//
// some state changes implemented here
//
const afterImage = await page.screenshot({
path: `./screenshots/after.png`
})
expect(beforeImage).toMatchSnapshot(afterImage)
});
but it does not work like this.
Any ideas/suggestions how can i achieve this?
Help would be greatly appreciated
You can do something like this:
test('compare screenshots', async ({ page }, testInfo)=>{
await page.goto(pageUrl);
const screenshotTarget = page.locator(scTarget);
await expect(screenshotTarget).toHaveScreenshot( `${testInfo.title}.png`);
//
// some state changes implemented here
//
await expect(screenshotTarget).toHaveScreenshot( `${testInfo.title}.png`);
});
I prefer to use the test titel for naming my screenshots but it should also work if you just enter the same name twice. Then if you run your tests without --update-snapshots they should fail if some visual changes happened.
The problem with Playwright's toHaveScreenshot and toMatchSnapshot is that they're a bit over-engineered and will only compare a current screenshot to a screenshot from a previous test run. If you want to compare two screenshots that you have as Buffers in memory, you can use the getComparator method that Playwright uses behind the scenes:
import { getComparator } from 'playwright-core/lib/utils';
await page.goto('my website here');
const beforeImage = await page.screenshot({
path: `./screenshots/before.png`
});
//
// some state changes implemented here
//
const afterImage = await page.screenshot({
path: `./screenshots/after.png`
});
const comparator = getComparator('image/png');
expect(comparator(beforeImage, afterImage)).toBeNull();
The advantage of using getComparator is that it fuzzy matches, and you can set the threshold of how many pixels are allowed to be different. If you just want to check that the PNGs are exactly identical, a dead simple method to check for equality between the two screenshots is:
expect(Buffer.compare(beforeImage, afterImage)).toEqual(0)
Beware though - this simpler method is flakey and sensitive to a single pixel difference in rendering (such as if any animations/transitions are not completed or if there are differences in anti-aliasing).
For analytic purposes I'd like to keep track on the client side of all the graphql operations (including ie #client ones). I was unable to find appropriate options in the API and wonder if this may be doable on the apollo-client level or may I need to introduce some proxy to intercept the calls by my own?
A custom Apollo link is a way to go.
You can use apollo-link-logger in particular to log all operations to console.
Usage (from docs):
import apolloLogger from 'apollo-link-logger';
// ...
ApolloLink.from([
apolloLogger,
// ...
]);
Note: Place apolloLogger before other links.
Output example:
As the answer from Yuriy was exactly what I was looking for I marked is as accepted answer - Thanks!
Still for the record here is the code doing a job for me - I believe someone may find it useful, also it is worth to show it's simplicity.
It's worth noting that Apollo links are chainable - thus the argument to a link function are operation: Operation and forward: NextLink which is supposed to be called from our link implementation.
let analytics: Analytics; // this is Fabric.io Analytics to be provided by DI
const analyticsLink = new ApolloLink((
operation: Operation,
forward?: NextLink
) => {
const operationType = operation.query.definitions[0].operation;
return forward(operation)
.map((result: FetchResult) => {
try {
analytics.sendCustomEvent(`${operationType}.${operation.operationName}`);
} catch (e) {
console.error('analytics error', e);
}
return result;
});
});
as a bonus we can also catch errors (i.e. to leverage fabric.io crashlytics) by using apollo-link-error (handling of errors in Apollo is a bit more complex);
const analyticsErrorLink = onError((error: ErrorResponse) => {
try {
// it's worth to rethink what we wanna log here
const message = error.graphQLErrors ? error.graphQLErrors[0].message :
(error.networkError.name + ': ' + error.networkError.message);
analytics.sendNonFatalCrash('GraphQL error: ' + message);
} catch(e) {
console.error('cannot report error to analytics', e);
}
});
Finally to compose the links we should put our intercepting implementations at the beginning so we will be able to catch all the GraphQL operations including those marked with #client which are not reaching network link - in my case full link looks like:
ApolloLink.from([
analyticsErrorLink,
analyticsLink,
stateLink,
auth,
http])
app.get('/:service[SOMETHING GOES HERE]', function(req, res, next){
console.log('Service is:', req.params.service);
});
This needs to catch URLs that can look like any one of:
/foo
/foo/bar
/foo/bar/baz
The call back isn't concerned with anything that comes after foo, but ideally should be able to access foo as a parameter called service without having to manually parse the path.
I've been using this to test and still haven't found anything that does exactly that. Closest so far is /:service*.
Edit: No it's not a duplicate of the one where the answer is /:service/* because that doesn't cover /foo.
Using /:service* in actual Express routes does exactly what you want:
/foo maps to { '0': '', service: 'foo' }
/foo/bar maps to { '0': '/bar', service: 'foo' }
/foo/bar/blah maps to { '0': '/bar/blah', service: 'foo' }
The Express Route Tester, for some reason, maps these URL's differently for that these kinds of patterns (it might be configured differently than Express).
You can use the app.use() function for that. Read the doc about path handling for more info. Your code once modified will be:
app.use('/foo', function(req, res, next){
console.log('Service is:', req.params.service);
});
The downside is that you are not going to recover foo as the service parameter.
// ex: http://example.com/john_smith
app.get('/^(a-z)_(0-9)', function(req, res) {
res.send('user');
});
// ex: http://example.com/john_smith/messages/1987234
app.get('/^(a-z)_(0-9)/messages/:id', function(req, res) {
res.send('message');
});
I wrote the above code for an app that I want to pass a username as a url variable to node.js like I would do: $username = $_GET['username']; in PHP. I'm not too good at writing regular expressions so I wanted to see if anyone could set me on the right track. Thanks in advance.
From your requirement it doesn't seem like you need a regular expression. Just use a a variable in your rule, like below:
// Grabs whatever comes after /user/ and maps it to req.params.id
app.get('/user/:id', function (req, res) {
var userId = req.params.id;
res.send(userId);
});
If you want to have better control, you could use a regular expression. To grab things you are interested in from the expression, use a capture group (which are typically expressed as a set of matching parenthesis):
// Grabs the lowercase string coming after /user/ and maps it to req.params[0]
app.get(/^\/user\/([a-z]+)$/, function (req, res) {
var userId = req.params[0];
res.send(userId);
});
A little off topic, but here's a really good intro to express.js that will help you understand it better (including how the routes work):
http://evanhahn.com/understanding-express-js/
You're looking for req.params, which is an array of all of the capture groups in the regex.
The capture groups start at 1; req.params[0] is the entire match.
I have tried to find a way to enter regular expression into an express routing URL and then access the variable portion of the URL through the request object. Specifically I want to route to the url "/posts/" + any number of digits. Is there a way to do this?
Examples:
/posts/54
/posts/2
/posts/546
This should do it:
app.get('/posts/:id(\\d+)', function(req, res) {
// id portion of the request is available as req.params.id
});
EDIT: added regex to path to limit it to digits
I agree with Johnny, my only addition being that you can do this for any number of levels. For example:
app.get('/users/:id/:karma', function(req, res){
//Both req.params.id and req.params.karma are available parameters.
});
You should also check out the express documentation: http://expressjs.com/api.html.
The request section would probably prove quite useful to you.