I have this code for testing my form
import { expect, test } from '#playwright/test'
test('Form test', async ({ page }) => {
await expect(page.locator('#feedback_form'))
await page.locator('input#name[type="text"]').fill('John Doe')
await page.locator('input#email[type="email"]').fill('troum#outlook.com')
await page.locator('input#phone[type="text"]').fill('+47 89 89678 90')
await page.locator('input#subject[type="text"]').fill('Test subject')
await page.locator('input#purpose[type="text"]').fill('Test purpose')
await page.locator('input#contactWay[type="text"]').fill('Via e-mail')
await page
.locator('textarea#message')
.fill('Contrary to popular belief, Lorem Ipsum is not simply random text')
await page.click('button[type="submit"]', { force: true })
await page.screenshot({ path: 'scrapingant.png' })
})
but I've got this problems for each browsers
it's my screenshort
Complete the assertion first:
await expect(page.locator('#feedback_form')).toBeVisible()
Then You can modify your selector a bit like this and try:
await page.locator('input#name').fill('John Doe')
Or, you can do a click before fill and try:
await page.locator('input#name').click().fill('John Doe')
try to use different selectors if its still not working,go for playwright Codegen's generated locator using command npx playwright codegen as i was facing the same issue and it worked for me even though i was using unique locator.
Related
The typical structure of my tests is as follows:
import {test} from '#playwright/test';
test.describe('suite', () => {
test('test1', async ({page}) => {
await page.goto('test1');
});
test('test2', async ({page}) => {
await page.goto('test2');
});
});
This works perfectly but I noticed that Playwright opens and closes the browser window for each test and was wondering, why the browser window cannot stay open for all tests and if this could/should be optimised?
Based on my feedback from a playwright contributor:
If you use the VSCode extension, the browser stays open: https://playwright.dev/docs/getting-started-vscode
You want to ensure full test isolation on your CI, what Playwright does it guarantees that so no test will infer with each other. (less reasons to flake)
I am working on a project where I am trying to achieve 'login one time to complete all my tests instead of logging in everytime for each test' I followed this document. My global setup looks exactly like how it is in the said document.
My test spec looks like this,
//sample.test.ts
test.describe("Login Tests", () => {
test.use({ storageState: "state.json" });
test(`TEST 1`, async ({ page }) => {
//browser launches in authenticated state
});
test(`Test 2`, async ({ page}) => {
//browser launches in unauthenticated state
});
});
//playwright.config.ts
globalSetup: require.resolve("./src/utility/globalSetup.ts"),
use: {
storageState: "state.json",
}
//globalSetup.ts
const { storageState } = config.projects[0].use;
const browser = await chromium.launch();
const page = await browser.newPage();
//code for login goes here....
await page.context().storageState({ path: storageState as string });
await browser.close();
The issue is my first test (TEST1) works fine - the browser launches in authenticated state. But my second test (TEST2) does not launch in authenticated state.
I tried running one test at a time. TEST1, TEST2 passes in isolated runs.
I swapped the test order, made TEST2 run first, in that case TEST2 launches in authenticated state TEST1 failed.
What could be the problem? Any help is highly appreciated.
I want to deploy a Lex bot to my AWS account using CDK.
Looking at the API reference documentation I can't find a construct for Lex. Also, I found this issue on the CDK GitHub repository which confirms there is no CDK construct for Lex.
Is there any workaround to deploy the Lex bot or another tool for doing this ?
Edit: CloudFormation support for AWS Lex is now available, see Wesley Cheek's answer. Below is my original answer which solved the lack of CloudFormation support using custom resources.
There is! While perhaps a bit cumbersome, it's totally possible using custom resources.
Custom resources work by defining a lambda that handles creation and deletion events for the custom resource. Since it's possible to create and delete AWS Lex bots using the AWS API, we can make the lambda do this when the resource gets created or destroyed.
Here's a quick example I wrote in TS/JS:
CDK Code (TypeScript):
import * as path from 'path';
import * as cdk from '#aws-cdk/core';
import * as iam from '#aws-cdk/aws-iam';
import * as logs from '#aws-cdk/aws-logs';
import * as lambda from '#aws-cdk/aws-lambda';
import * as cr from '#aws-cdk/custom-resources';
export class CustomResourceExample extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Lambda that will handle the different cloudformation resource events
const lexBotResourceHandler = new lambda.Function(this, 'LexBotResourceHandler', {
code: lambda.Code.fromAsset(path.join(__dirname, 'lambdas')),
handler: 'lexBotResourceHandler.handler',
runtime: lambda.Runtime.NODEJS_14_X,
});
lexBotResourceHandler.addToRolePolicy(new iam.PolicyStatement({
resources: ['*'],
actions: ['lex:PutBot', 'lex:DeleteBot']
}))
// Custom resource provider, specifies how the custom resources should be created
const lexBotResourceProvider = new cr.Provider(this, 'LexBotResourceProvider', {
onEventHandler: lexBotResourceHandler,
logRetention: logs.RetentionDays.ONE_DAY // Default is to keep forever
});
// The custom resource, creating one of these will invoke the handler and create the bot
new cdk.CustomResource(this, 'ExampleLexBot', {
serviceToken: lexBotResourceProvider.serviceToken,
// These options will be passed down to the lambda
properties: {
locale: 'en-US',
childDirected: false
}
})
}
}
Lambda Code (JavaScript):
const AWS = require('aws-sdk');
const Lex = new AWS.LexModelBuildingService();
const onCreate = async (event) => {
await Lex.putBot({
name: event.LogicalResourceId,
locale: event.ResourceProperties.locale,
childDirected: Boolean(event.ResourceProperties.childDirected)
}).promise();
};
const onUpdate = async (event) => {
// TODO: Not implemented
};
const onDelete = async (event) => {
await Lex.deleteBot({
name: event.LogicalResourceId
}).promise();
};
exports.handler = async (event) => {
switch (event.RequestType) {
case 'Create':
await onCreate(event);
break;
case 'Update':
await onUpdate(event);
break;
case 'Delete':
await onDelete(event);
break;
}
};
I admit it's a very bare-bones example but hopefully it's enough to get you or anyone reading started and see how it could be built upon by adding more options and more custom resources (for example for intentions).
Deploying Lex using CloudFormation is now possible.
CDK support has also been added but it's only available as an L1 construct, meaning the CDK code is basically going to look like CloudFormation.
Also, since this feature just came out, some features may be missing or buggy. I have been unable to find a way to do channel integrations, and have had some problems with using image response cards, but otherwise have successfully deployed a bot and connected it with Lambda/S3 using CDK.
I'm trying to test my electron app with spectron and mocha;my application will close the first window after user login,so i need add some "wait action" to wait the second window to appear. But it seems setTimeout's callback works abnormal.
I think the settimeout function works asynchronous, so the promise chain will continue after you started the settimeout. So somehow you have to await the settimeout - have you tried wrapping it in a promise, and then return the promise?
return new Promise((resolve, reject) => {
setTimeout(async () => {
await this.app.client.windowByIndex(0); //I'm not even sure you need to await this
resolve();
}, 3000);
});
After signing in using two-factor with authenticator app, I set rememberClient to true like this:
await _signInManager.TwoFactorAuthenticatorSignInAsync(code: request.Code,
isPersistent: request.IsPersistent,
rememberClient: request.RememberClient);
Signing in works fine and I get the .AspNetCore.Identity.Application and Identity.TwoFactorRememberMe cookies. If I sign out and in again I don't need to use two-factor. So long everything is fine.
The problem is when I do some changes in the user, like the phone number, and the SecurityStamp is changed. After the change is made I use await _signInManager.RefreshSignInAsync(user). But the Identity.TwoFactorRememberMe cookie isn't updated. This results in two problems:
The next time I sign in I have to use the two-factor authentication again.
During the same session, if I check if the user has remembered the browser, using await _signInManager.IsTwoFactorClientRememberedAsync(user), it will result in an error "Failed to validate a security stamp" and the .AspNetCore.Identity.Application will be removed.
I've tried to renew the Identity.TwoFactorRememberMe cookie at the same time as the .AspNetCore.Identity.Application cookie, like this:
await base.RefreshSignInAsync(user);
await RememberTwoFactorClientAsync(user);
It works, but it will also set the Identity.TwoFactorRememberMe cookie for those who didn't have it before. I can't check if it is set before, because then I get the error I described in (2) above.
The next thing I will try is to do something like this for every place I do something which changes the user SecurityStamp:
var isTwoFactorClientRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user);
// do the changes...
await _signInManager.RefreshSignInAsync(user);
if (isTwoFactorClientRememberedAsync)
await _signInManager.RememberTwoFactorClientAsync(user);
Is there something I'm missing here, or is this the only way to go?
I'm using IdentityServer4 and a SPA app, but I don't believe that has anything to do with the problem.
I ended up adding a method in my custom ApplicationSignInManager:
public async Task<TResult> KeepSignInAsync<TResult>(ApplicationUser user, Func<Task<TResult>> func)
{
var isTwoFactorClientRemembered = await IsTwoFactorClientRememberedAsync(user);
var result = await func();
await RefreshSignInAsync(user);
if (isTwoFactorClientRemembered)
await RememberTwoFactorClientAsync(user);
return result;
}
When I change something which will update the user SecurityStamp I use it like this:
var result = await _signInManager.KeepSignInAsync(user, () => _userManager.SetPhoneNumberAsync(user, phoneNumber));