How can I set up localStorage keys with storageState - playwright

I'm trying to set up localStorage when a user registers,
but it only generates the file with no key, values.
If I run npx playwright codegen --save-storage=formsData.json
works fine and generates the key,values but the generated code is very different
and I don't see how localStorage is created.
What I'm doing wrong, or not doing ?
This is my test code:
const { test, expect } = require('#playwright/test');
const { buildUser } = require('./utils/generateUser');
test.describe('Register Form', () => {
test('displays register form and can register user', async ({ browser }) => {
const user = await buildUser();
const page = await browser.newPage();
await page.goto('http://localhost:3000/register');
await expect(page).toHaveURL('http://localhost:3000/register');
const firstNameInput = page.locator('[placeholder="Nombre"]');
const lastNameInput = page.locator('[placeholder="Apellidos"]');
const emailInput = page.locator('[placeholder="Email"]');
const passwordInput = page.locator('[placeholder="Contraseña"]');
const repeatPasswordInput = page.locator('[placeholder="Repite la contraseña"]');
const registerButton = page.locator('text=Adelante');
const termsCheckbox = page.locator('input[type="checkbox"]').first();
const privacyCheckbox = page.locator('input[type="checkbox"]').last();
const modalWindow = page.locator('.styles__ContentWrapper-n48cq5-0');
const modalButton = page.locator('text=Aceptar');
await expect(firstNameInput).toBeEmpty();
await expect(lastNameInput).toBeEmpty();
await expect(emailInput).toBeEmpty();
await expect(passwordInput).toBeEmpty();
await expect(repeatPasswordInput).toBeEmpty();
await expect(registerButton).toBeDisabled();
await expect(termsCheckbox).not.toBeChecked();
await expect(privacyCheckbox).not.toBeChecked();
await expect(modalWindow).toBeHidden();
await firstNameInput.fill(user.nombre);
await lastNameInput.fill(user.apellido);
await emailInput.fill(user.email);
await passwordInput.fill('12341234');
await repeatPasswordInput.fill('12341234');
await termsCheckbox.check();
await privacyCheckbox.click();
await expect(modalWindow).toBeVisible();
await page.press(':nth-match(input[type="checkbox"], 2)', 'Tab');
await page.press('text=info#coinscrap.com', 'Tab');
await await modalButton.click();
await expect(registerButton).toBeEnabled();
await registerButton.click();
await page.context().storageState({ path: 'formsData.json' });
await browser.close();
});
});
This is what playwright codegen does:
const { test, expect } = require('#playwright/test');
test('test', async ({ page }) => {
// Go to http://localhost:3000/register
await page.goto('http://localhost:3000/register');
// Click [placeholder="Nombre"]
await page.click('[placeholder="Nombre"]');
// Fill [placeholder="Nombre"]
await page.fill('[placeholder="Nombre"]', 'Pascale');
// Click [placeholder="Apellidos"]
await page.click('[placeholder="Apellidos"]');
// Fill [placeholder="Apellidos"]
await page.fill('[placeholder="Apellidos"]', 'Gusikowski');
// Click [placeholder="Email"]
await page.click('[placeholder="Email"]');
// Fill [placeholder="Email"]
await page.fill('[placeholder="Email"]', 'Pascale_Gusikowski86#gmail.com');
// Click [placeholder="Contraseña"]
await page.click('[placeholder="Contraseña"]');
// Fill [placeholder="Contraseña"]
await page.fill('[placeholder="Contraseña"]', '12341234');
// Click [placeholder="Repite la contraseña"]
await page.click('[placeholder="Repite la contraseña"]');
// Fill [placeholder="Repite la contraseña"]
await page.fill('[placeholder="Repite la contraseña"]', '12341234');
// Check input[type="checkbox"]
await page.check('input[type="checkbox"]');
// Click text=1.1 -Decisiones automatizadas, perfiles y lógica aplicada Los datos recogidos me
await page.click('text=1.1 -Decisiones automatizadas, perfiles y lógica aplicada Los datos recogidos me');
// Press End
await page.press('text=You need to enable JavaScript to run this app. Crea una cuenta​​​​​ AdelanteHe l', 'End');
// Click text=Aceptar
await page.click('text=Aceptar');
// Click text=Adelante
await Promise.all([
page.waitForNavigation(/*{ url: 'http://localhost:3000/internal/banks/start' }*/),
page.click('text=Adelante')
]);
});
There's no code where localStorage is created.
I need to do it programmatically.
I've also tried with:
const localStorage = await page.evaluate(() => JSON.stringify(window.localStorage));
fs.writeFileSync('formsData.json', localStorage);
It generates the file but didn't generate keys, values.

localStorage (DOMStorage) is unrelated to the form you submit. When you submit the form, a POST request is typically issued to the server, sending on this data to the backend. It looks like your page has additional JavaScript code that stores these values into localStorage at some point. Your localStorage does not have these values at the time you save it, so you should figure out how to trigger this code on your page and how to wait for it. You can open DevTools and evaluate "localStorage" in console or pick it in the Application tab to see when and why these values make their way into the local storage.

Related

PlayWright: Page.title() returning empty value. Trying to add automation in electron-vue project

For automated testing, I'm attempting to incorporate Playwright into my electron-vue project. I run the test, and Page.title() returns "". Here is the code:
test("renders the screen splash", async () => {
let page: Page;
page = await electronApp.firstWindow();
console.log("Title: ", await page.title());
const title = await page.title()
expect(title).toBe('Splash')
});
Could you try if it helps?
test("renders the screen splash", async () => {
let page: Page;
page = await electronApp.firstWindow();
// add the following line
await page.waitForLoadState();
console.log("Title: ", await page.title());
const title = await page.title()
expect(title).toBe('Splash')
});

Data sharing between Safari and standalone iPhone 12 iOS 14.3

I tried to share data between Safari browser and standalone PWA on iPhone12 with iOS 14.3.
The information, that this should work are here: https://firt.dev/ios-14/
I#ve tried this: https://www.netguru.com/codestories/how-to-share-session-cookie-or-state-between-pwa-in-standalone-mode-and-safari-on-ios
Without success.
Are there any suggestions to running this? Or is it not possible ...
This is the code
const CACHE_NAME = "auth";
const TOKEN_KEY = "token";
const FAKE_TOKEN = "sRKWQu6hCJgR25lslcf5s12FFVau0ugi";
// Cache Storage was designed for caching
// network requests with service workers,
// mainly to make PWAs work offline.
// You can give it any value you want in this case.
const FAKE_ENDPOINT = "/fake-endpoint";
const saveToken = async (token: string) => {
try {
const cache = await caches.open(CACHE_NAME);
const responseBody = JSON.stringify({
[TOKEN_KEY]: token
});
const response = new Response(responseBody);
await cache.put(FAKE_ENDPOINT, response);
console.log("Token saved! 🎉");
} catch (error) {
// It's up to you how you resolve the error
console.log("saveToken error:", { error });
}
};
const getToken = async () => {
try {
const cache = await caches.open(CACHE_NAME);
const response = await cache.match(FAKE_ENDPOINT);
if (!response) {
return null;
}
const responseBody = await response.json();
return responseBody[TOKEN_KEY];
} catch (error) {
// Gotta catch 'em all
console.log("getToken error:", { error });
}
};
const displayCachedToken = async () => {
const cachedToken = await getToken();
console.log({ cachedToken });
};
// Uncomment the line below to save the fake token
// saveToken(FAKE_TOKEN);
displayCachedToken();
Without success means no result, i've tried to set data in safari and get them in standalone pwa

Getting value of input element in Playwright

How do I return the value of elem so that I can verify that it is in fact 1?
const elem = await page.$('input#my-input')
await elem.fill('1')
inputValue method has been added in Playwright v1.13.0
await page.inputValue('input#my-input');
Locator:
await page.locator('input#my-input').inputValue();
It returns input.value for the selected <input> or <textarea> element. Throws for non-input elements. Read more.
The easiest way is to use $eval. Here you see a small example:
const playwright = require("playwright");
(async () => {
const browser = await playwright.chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
await page.setContent(`<input id="foo"/>`);
await page.type("#foo", "New value")
console.log(await page.$eval("#foo", el => el.value))
await page.screenshot({ path: `example.png` });
await browser.close();
})();
From version 1.19 (and probably lower versions) Element Handler is not recomended.
Instead of it use Locator.
page.locator(selector).innerText()
in your case with assertion it will be
expect(page.locator("input#my-input").innerText().includes("1")).toBeTruthy()
Read more on:
https://playwright.dev/docs/api/class-elementhandle#element-handle-fill

Timeout - Async callback was not invoked within the 60000ms

import wd from 'wd';
jest.setTimeout(60000);
const PORT = 4723;
const config = {
platformName: 'iOS',
deviceName: `iPhone X`,
platformVersion: '12.2',
app: '/path/to/my.app',
useNewWDA: true,
autoLaunch: false,
};
let screenshotIndex = 0
const driver = wd.promiseChainRemote('localhost', PORT);
directory = '../screenshots';`enter code here`
beforeAll(async () => {
await driver.init(config);
await driver.sleep(7000); // wait for app to load
});
afterEach(async () => {
await driver.takeScreenshot().then(
function (image, err) {
require('fs').writeFile(`screenshot-${screenshotIndex++}.png`, image, 'base64');
}
);
});
test('appium renders', async () => {
let contexts = await driver.contexts();
console.log('contexts', contexts);
await driver.context(contexts[1]);
await driver.elementById('username').type('abc#example.com');
await driver.elementById('password').type('#1234');
await driver.elementById('Login').click();
});
//Timeout - Async callback was not invoked within the 60000ms timeout specified by jest.setTimeout.Error: Timeout - Async callback was not invoked within the 60000ms timeout specified by jest.setTimeout.
After I run this I get the above error. Not sure where am i going wrong
Try setting setTimeout to node setTimeout rather than default jest.setTimeout
// add below after import
global.setTimeout = require("timers").setTimeout

How to fix slow issue when using async and await for caching using Sqflite?

I store all API data to cache. some APIs have more than 10000 data. Postman response time is within one second. but in application very slow to navigate to next page. I used this code:
onPressed: () async {
...
}
else {
var token = Token(
id: 1,
token: tokens,
refreshToken: model.data.refreshToken,
);
await storeRegister(_url,tokens);
await storeEquipmentReg(_url,tokens);
await storeSyncLogin(_url,tokens);
await HelperDefCatMaster().deleteDefCatMaster();
await storeDefCatMaster(_url,tokens);
await HelperDefRegisterCat().deleteDefRegisterCat();
await storeDefRegisterCat(_url,tokens);
await HelperDefCatMaster().deleteDefCatRelation();
await storeDefCatRelation(_url,tokens);
await HelperDefCatMaster().deleteWoDescription();
await storeWoDescription(_url,tokens);
await HelperDefCatMaster().deleteCategoryDefect();
await storeCategoryDefect(_url,tokens);
await storeWorkSource(_url,tokens);
await storeWorkTypes(_url,tokens);
await storePriorities(_url,tokens);
await Helper().insert(token);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ListPage(model.data.token)));
}
storePriorities function look like,
storePriorities(String url, String token) async {
final response = await http.get(
'${url}/v1.0/Priorities',
headers: {'Authorization': 'Bearer ${token}'},
);
final jsonResponse = json.decode(response.body);
Priorities model = Priorities.fromJson(jsonResponse);
int length = model.data.length;
for (int i = 0; i < length; i++) {
var data = DataPriorities(
i: model.data[i].i,
d: model.data[i].d,
);
await HelperDefCatMaster().insertPriorities(data);
}
}
I have given the first answer that suggests to use await only when it's needed.
Well if you are inserting too much data in SQLite I assume that you might be using something like this:
for (int i = 0; i <= 1000; i++) {
db.insert('table_name', dataObject.toMap());
}
Well this will do a lot many transactions at a time and it will consume a lot's of your time.
Change this to something like this and it will increase the speed of inserting data:
Batch batch = db.batch();
for (int i = 0; i <= 1000; i++) {
batch.insert('table_name', dataObject.toMap());
}
await batch.commit();
What we are doing here is that, in single transaction we are doing multiple inserts at a time.
I made this change in my demo project where I was inserting 1000 row at a time and results were great. db.insert when called 1000 times took 7 secs where as batch.insert took less than 1 sec for inserting same amount of data.
If you optimize your code with this solution and use await when needed you should not face any problem on UI. Let me know if this helps.
You are using await keyword to fetch data from SQLite.
And you are fetching a lots of data.
This will make data fetching synchronous, and will affect your UI.
If it is convenient for your use-case to fetch data asynchronously then you can use the following way:
Change :
await Helper().insert(token);
Navigator.push(
context,MaterialPageRoute(builder: (context) => ListPage(model.data.token)));
to :
Helper().insert(token).then((onValue) {
Navigator.push(context,MaterialPageRoute(
builder: (context) => ListPage(model.data.token),
),
);
}
Note: Make your insert method return Future<'token's return type'>
Now use this way for all other await calls.

Resources