How to take page access by puppeteer after clicking on href link? - url

Suppose, In a website I have some link to test that each link is working good.For that, I need to click each page link and need to test each page is opening and I need to assert the opened page content.
How's that possible using puppeteer?

If the links are common links with a href attribute, you can collect all URLs first and then test them in a loop like this:
const puppeteer = require('puppeteer');
(async function main() {
try {
const browser = await puppeteer.launch();
const [page] = await browser.pages();
await page.goto('https://example.org/');
const hrefs = await page.evaluate(() => {
return Array.from(
document.querySelectorAll('a[href]'),
a => a.href,
);
});
for (const url of hrefs) {
console.log(url);
await page.goto(url);
const data = await page.evaluate(() => {
return document.title;
});
console.log(data);
}
await browser.close();
} catch (err) {
console.error(err);
}
})();

Related

How to respond with a stream in a Sveltekit server load function

Below I try to respond with a stream when I receive ticker updates.
+page.server.js:
import YahooFinanceTicker from "yahoo-finance-ticker";
const ticker = new YahooFinanceTicker();
const tickerListener = await ticker.subscribe(["BTC-USD"])
const stream = new ReadableStream({
start(controller) {
tickerListener.on("ticker", (ticker) => {
console.log(ticker.price);
controller.enqueue(ticker.price);
});
}
});
export async function load() {
return response????
};
Note: The YahooFinanceTicker can't run in the browser.
How to handle / set the response in the Sveltekit load function.
To my knowledge, the load functions cannot be used for this as their responses are JS/JSON serialized. You can use an endpoint in +server to return a Response object which can be constructed from a ReadableStream.
Solution: H.B. comment showed me the right direction to push unsollicited price ticker updates the client.
api route: yahoo-finance-ticker +server.js
import YahooFinanceTicker from "yahoo-finance-ticker";
const ticker = new YahooFinanceTicker();
const tickerListener = await ticker.subscribe(["BTC-USD"])
/** #type {import('./$types').RequestHandler} */
export function GET({ request }) {
const ac = new AbortController();
console.log("GET api: yahoo-finance-ticker")
const stream = new ReadableStream({
start(controller) {
tickerListener.on("ticker", (ticker) => {
console.log(ticker.price);
controller.enqueue(String(ticker.price));
}, { signal: ac.signal });
},
cancel() {
console.log("cancel and abort");
ac.abort();
},
})
return new Response(stream, {
headers: {
'content-type': 'text/event-stream',
}
});
}
page route: +page.svelte
<script>
let result = "";
async function getStream() {
const response = await fetch("/api/yahoo-finance-ticker");
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
while (true) {
const { value, done } = await reader.read();
console.log("resp", done, value);
if (done) break;
result += `${value}<br>`;
}
}
getStream();
</script>
<section>
<p>{#html result}</p>
</section>

Is there a way to have my service worker intercept fetch requests coming from a client-side SvelteKit load function? (+page.ts)

I'm trying to have a service worker intercept fetch requests coming from a client-side SvelteKit load function. The network requests are being made, but the fetch event is not being triggered.
The fetch request from the load function is going to /api/allTeams, which is cached as reported by chrome devtools, but like I said, it's not getting intercepted. All the function does it fetch the data, and return it in a prop.
Also, every couple minutes I run invalidateAll(), to reload the data, and even those requests aren't being picked up by the SW.
Thanks!
--reese
src/service-worker.js:
import { build, version } from '$service-worker';
self.addEventListener('fetch', function (event) {
console.log("fetch")
event.respondWith(
fetch(event.request).catch(function () {
return caches.match(event.request);
}),
);
});
self.addEventListener('install', async function (event) {
event.waitUntil(
caches.open("ccs-" + version).then(function (cache) {
cache.add("/api/allTeams")
cache.addAll(build)
return;
}),
);
});
src/app.html:
<script>
const registerServiceWorker = async () => {
if ("serviceWorker" in navigator) {
try {
const registration = await navigator.serviceWorker.register("/service-worker.js", {
scope: "*",
});
if (registration.installing) {
console.log("Service worker installing");
} else if (registration.waiting) {
console.log("Service worker installed");
} else if (registration.active) {
console.log("Service worker active");
}
} catch (error) {
console.error(`Registration failed with ${error}`);
}
}
};
registerServiceWorker()
</script>
src/+page.ts:
export async function load(request: Request) {
const searchQuery = new URL(request.url).searchParams.get("q")
const apiUrl = new URL(request.url)
apiUrl.pathname = "/api/allTeams"
const req = await fetch(apiUrl)
const data = await req.json()
return {data, searchQuery};
}

Exporting a Test To Another File?

I have a file structure that looks like this
Folder Structure
I have a file called "login.js" that will contain a function that logs into the page. Currently it looks like this
// login.js
const { chromium } = require('playwright');
async function Login() {
const browser = await chromium.launch({
headless: false,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('http://test.local/');
return true;
}
/*
This is just a example of logging in and not complet
*/
I want to export it so all my other tests can continue AFTER this one function logs in. Once it successfully logs in, tests such as 'example.spec.js' can get all the cookies/headers from the login script and continue
How can I do that?
You should be doing this.
// login.js
const { chromium } = require('playwright');
module.exports = async function login() {
const browser = await chromium.launch({
headless: false,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('http://test.local/');
return true;
}
Then you can access it in another file like this.
const login = require('./test.js'); // path has to be altered based on your folder structure
login();

How to redirect to original page after login with remix-auth-auth0

Related to : How to redirect back to original page after login / signup in remix-auth?
If a user try to access to a protected routes, I want him to login, and then be redirected to this route.
With remix-auth, I have this in protected route :
export let loader: LoaderFunction = async ({ request }) => {
return await authenticator.isAuthenticated(request, {
failureRedirect: "/login?redirectTo=/search",
});
};
Then in my login route :
export let loader: LoaderFunction = async ({ request }) => {
return await login(request);
};
With function login() to be :
export async function login(request: Request) {
let url = new URL(request.url);
let returnTo = url.searchParams.get("redirectTo") as string | null;
try {
// call authenticate as usual, in successRedirect use returnTo or a fallback
return await authenticator.authenticate("auth0", request, {
successRedirect: returnTo ?? "/search",
failureRedirect: "/",
});
} catch (error) {
if (error instanceof Response && error.redirected) {
const returnToCookie = createCookie("returnToCookie");
error.headers.append(
"Set-Cookie",
await returnToCookie.serialize(returnTo)
);
}
throw error;
}
}
And finally the callback route is :
export let loader: LoaderFunction = async ({ request }) => {
//get the returnTo from the cookie
const returnToCookie = createCookie("returnToCookie");
const result = await returnToCookie.parse(request.headers.get("Cookie"));
let returnTo = (result) ?? "/";
return await authenticator.authenticate("auth0", request, {
successRedirect: returnTo,
failureRedirect: "/",
});
};
The problem is that login() function currently redirect the user to callback url (with the code in url), but with nothing special in cookie, so the callback route use the fallback.
If I try&catch login() function in login route, the erreur obtained is a Response, but not a redirect, so nothing special in the cookie too (and I don't really know what to do with this Response error)
I not sure of what I missed in the original post.
After some tries, I found the solution :
The login() function return a 302 HTTP code which is a redirection, but do not trigger the if (error instanceof Response && error.redirected)
Simply remove && error.redirected of the condition make the redirection work perfectly.

How to send a result to sender via contextBridge / IPCRenderer?

I have a electron that looks like this
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electron', {
electronStore: {
get(val) {
ipcRenderer.send('electron-store-get', val);
},
set(property, val) {
ipcRenderer.send('electron-store-set', property, val);
},
// Other method you want to add like has(), reset(), etc.
},
});
and ipcMain that looks like this
ipcMain.on('electron-store-get', async (event, val) => {
store.get(val);
// console.log(reply);
// return reply;
// event.reply('electron-store-get', reply);
});
ipcMain.on('electron-store-set', async (event, property, val) => {
// console.log(val);
store.set(property, val);
});
When I was trying to call the function via electron.electronStore.get(), it returns undefined
let a = window.electron.electronStore.get('test');
console.log(a);
However, I've tested that on the line of ipcRenderer.send(""), I was able to receive data by setting as below
let result = ipcRenderer.send('electron-store-get',val);
console.log(result);
Which mean, ipcRenderer is not undefined and set has been successfuly, get as-well, just it went missing when i invoke the ipcMain Get functions
Your current preload API isn't actually returning anything:
get(val) {
ipcRenderer.send('electron-store-get', val);
}
You'll want to either use the synchronous API: return ipcRenderer.sendSync('electron-store-get', val) and then have your handler in main do:
ipcMain.on('electron-store-get', (event, val) => {
event.returnValue = store.get(val);
});
Or make the preload API async:
get(val) {
return ipcRenderer.invoke('electron-store-get', val);
}
ipcMain.handle('electron-store-get', (event, val) => {
return store.get(val);
});
And then:
let a = await window.electron.electronStore.get('test');

Resources