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();
Related
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>
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};
}
Abstract:
Launch the Chrome extension background page and continue with the test.
How is it implemented?
All the pages are (Login, Admin pages) with the page object model.
Invoke the persistent context browser with the chrome extension URL and pass the page reference to each page constructor.
Use the page instance in the test and call the respective page actions.
What is a problem statement?
Able to launch the persistence context browser and navigate to the chrome extension URL.
However, page reference is passed to the target page and when it performs the action, it is throwing an error as the target is closed.
Sorry, I am new to Typescript. Came from java background.
Console Error:
Action was interrupted
public async search(): Promise<void> {
10 | console.log(this.browserPage.title());
| ^
11 | await this.browserPage.type('input[name="q"]', "Playwright")
Note: I have provided the google search for demonstration. But the approach is the same.
Test File: chromeextensionstest.spec.ts
import { BrowserContext, chromium, expect, Page, test } from "#playwright/test";
import path from "path";
import { SearchPage } from "../pages/admin/search.spec";
var browserContext: BrowserContext;
var browserPage: Page;
var basePath = require("path").resolve(__dirname, "..");
test.describe("test", async () => {
test.beforeAll(async ({ browser }) => {
browserContext = await chromium.launchPersistentContext("", {
headless: false,
channel: "chrome",
acceptDownloads: true,
recordVideo: {
dir: "videos",
size: { width: 640, height: 480 },
},
slowMo: 500,
strictSelectors: false,
//args: [
// `--disable-extensions-except=${extensionDir},${widgetDir}`,
// `--load-extension=${extensionDir},${widgetDir}`,
//],
});
browserContext.grantPermissions([
"notifications",
"clipboard-read",
"clipboard-write",
]);
browserPage = await browserContext.newPage();
});
test("Navigate to Google", async () => {
let extensionUrl = 'https://google.com';
await browserPage.goto(extensionUrl);
let searchPage = new SearchPage(browserPage);
searchPage.search();
});
});
Search POM: search.spec.ts
// #ts-check
import { expect, Page } from "#playwright/test";
export class SearchPage {
browserPage: Page;
constructor(page: Page) {
this.browserPage = page;
}
public async search(): Promise<void> {
console.log(this.browserPage.title());
await this.browserPage.type('input[name="q"]', "Playwright")
await this.browserPage.keyboard.press('Enter');
let text = await this.browserPage.innerText('//h3[contains(text(),"Playwright:")]')
expect(text).toContain('Playwright: Fast and reliable');
}
}
I can't figure out why this doesn't work.
my module under test is this dockerService:
const Docker = require('dockerode');
const docker = new Docker();
[...]
async function appDockerStart(idOrName) {
// container ID or name
const containers = await dockerListContainers(true);
const myContainer = containers.find([...] using containers);
const dockerContainer = docker.getContainer(myContainer.Id);
await dockerContainer.start(); <=== this is what I'm trying to stub
return `started.`;
}
my test
describe('tests', () => {
const appName = 'website';
let containerStub;
beforeEach(() => {
containerStub = {
start: sinon.stub().returns('started'),
};
const dockerodeStub = {
Container: containerStub,
};
dockerService = proxyquire('../../dockerService',
{
dockerode: dockerodeStub,
});
});
afterEach(() => {
sinon.restore();
});
it('should return a valid stats object', async () => {
const res = await dockerService.appDockerStart(appName);
});
});
but I'm getting an error - TypeError: Docker is not a constructor
it seems like the first file is failing on const docker = new Docker();
the dockerode itself a namespace which has a class Container etc etc.
How do I go about it without modifying the first file?
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);
}
})();