I was executing Protractor Cucumber test with Jenkins, and in Cucumber Report last executed step is appearing In After step twice - - protractor

I was executing Protractor Cucumber test with Jenkins, and in Cucumber Report last executed step is appearing In After step twice in report under Jenkins, Please suggest
here is my hook-
const { After, Before, AfterAll, Status } = require("cucumber");
import { browser, protractor } from "protractor";
Before({ timeout: 100 * 1000 }, async () => {
await browser.get(config.baseUrl);
});
After(async function (scenario) {
if (scenario.result.status === Status.FAILED) {
const screenShot = await browser.takeScreenshot();
this.attach(screenShot, "image/png");
browser.actions().sendKeys(protractor.Key.ESCAPE).perform();
await helper.logoutFromApplication();
}
});
AfterAll({ timeout: 100 * 1000 }, async () => {
await browser.quit();
});
refer the report for the same-

Related

mongo-memory-server/nest process failed to exit gracefully. Likely leak on teardown

I have Mongoose In memory test helper that I'm using with a controller test:
Helper
import { MongooseModule, MongooseModuleOptions } from '#nestjs/mongoose';
import { MongoMemoryServer } from 'mongodb-memory-server';
import { connection } from 'mongoose';
let mongod: MongoMemoryServer;
export const rootMongooseTestModule = (options: MongooseModuleOptions = {}) =>
MongooseModule.forRootAsync({
useFactory: async () => {
mongod = await MongoMemoryServer.create();
const mongoUri = await mongod.getUri();
return {
uri: mongoUri,
...options,
};
},
});
export const closeInMongodConnection = async () => {
connection.dropDatabase();
connection.close();
if (mongod) await mongod.stop();
};
export const removeCollections = async () => {
const collections = connection.collections;
for (const key in collections) {
const collection = collections[key];
await collection.deleteMany({});
}
}
UserController Test
import { Test, TestingModule } from '#nestjs/testing';
import { MongooseModule } from '#nestjs/mongoose';
import {
closeInMongodConnection,
removeCollections,
rootMongooseTestModule,
} from '../../test/utils/MongooseTestModule';
import { UserSchema } from './user.schema';
import { UserController } from './user.controller';
import { UserService } from './user.service';
describe('UserController', () => {
let controller: UserController;
const mockUser = {
username: 'kyle',
email: 'kyle#example.com',
password: 'password',
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [UserController],
imports: [
rootMongooseTestModule(),
MongooseModule.forFeature([{ name: 'User', schema: UserSchema }]),
],
providers: [UserService],
}).compile();
controller = module.get<UserController>(UserController);
});
afterAll(async () => {
await closeInMongodConnection();
});
afterEach(async () => {
await removeCollections();
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
describe('create', () => {
it('should return the saved object', async () => {
const createdUser = await controller.create(mockUser);
expect(createdUser.username).toBe(mockUser.username);
});
});
});
After the test I close the connection and remove all collections, but for some reason I'm still getting:
npm test --detectOpenHandles
tried this too:
npm test --runInBand --detectOpenHandles
A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --detectOpenHandles to find leaks. Active timers can also cause this, ensure that .unref() was called on them.
The test does finish and doesn't hang:
Test Suites: 15 passed, 15 total
Tests: 16 passed, 16 total
Snapshots: 0 total
Time: 5.369 s
When I add await connection.dropDatabase(); in the closeInMongodConnection function my tests take about 3 more seconds.
Is there anyway to fix this error? Is this just happening because opening and closing mongo connections is slow? I'm not sure what's going on because it seems like I'm doing everything I'm suppose too
Edit:
After un commenting await connection.dropDatabase(); I'm now getting:
thrown: "Exceeded timeout of 5000 ms for a hook.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

One time authentication in playwright is giving issues

I tried to have a one time authentication using session and use the same for all the tests in the spec file.
While trying to run my test , sometimes i get this below error which im unable to underdstand or fix. Any help on this would be appreciated.
browser.newContext: Cookie should have a valid expires, only -1 or a positive number for the unix timestamp in seconds is allowed
at C:\Users\v.shivarama.krishnan\source\repos\PlaywrightDemo\node_modules\#playwright\test\lib\index.js:595:23
at Object.context [as fn] (C:\Users\v.shivarama.krishnan\source\repos\PlaywrightDemo\node_modules\#playwright\test\lib\index.js:642:15)
Spec.ts
import { chromium, test, expect } from "#playwright/test";
test.describe('Launch Browser', () => {
await context.storageState({ path: 'storage/admin.json' });
await page.goto('abc.com');
await expect(page.locator('#ebiLink')).toBeVisible();
const texts = await page.locator('#ebiLink').textContent();
console.log("text of ebi is " + texts);
await page.goto('abc.com');
await expect(page.locator('text= Detailed Interfaces ')).toBeVisible();
await page.waitForSelector('#searchTab');
await page.waitForSelector('#InterfaceCard');
await page.locator('#searchTab').type('VISHW-I7939');
await page.locator("button[type='button']").click();
await page.locator('#InterfaceCard').first().click();
await expect(page.locator('#ngb-nav-0')).toBeVisible();
const interfaceID = await page.locator("//span[#class='value-text']").first().allInnerTexts();
console.log('interface id is' + interfaceID);
const dp = await page.waitForSelector('role=listbox');
await page.locator('role=listbox').click();
const listcount = await page.locator('role=option').count();
await page.locator('role=option').nth(1).click();
await expect(page.locator('#ngb-nav-0')).toBeVisible();
});
test('Move to shells screen', async ({ page, context }) => {
await context.storageState({ path: 'storage/admin.json' });
await page.goto('abc.com');
await expect(page.locator('#ListHeader')).toBeVisible();
const shells = await page.locator('#ListHeader').textContent();
console.log('Text of shells header is '+shells);
});
});
global-setup.ts (for one time login and getting the session)
import { Browser, chromium, FullConfig } from '#playwright/test'
async function globalSetup(config: FullConfig) {
const browser = await chromium.launch({
headless: false
});
await saveStorage(browser, 'Admin', 'User', 'storage/admin.json')
await browser.close()
}
async function saveStorage(browser: Browser, firstName: string, lastName: string, saveStoragePath: string) {
const page = await browser.newPage()
await page.goto('abc.com');
await page.waitForSelector("//input[#type='email']", { state: 'visible' });
await page.locator("//input[#type='email']").type('ABC#com');
await page.locator("//input[#type='submit']").click();
await page.locator("//input[#type='password']").type('(&^%');
await page.locator("//input[#type='submit']").click();
await page.locator('#idSIButton9').click();
await page.context().storageState({ path: saveStoragePath })
}
export default globalSetup
Have you registered global-setup.ts script in the Playwright configuration file: like below?
// playwright.config.ts
import { PlaywrightTestConfig } from '#playwright/test';
const config: PlaywrightTestConfig = {
globalSetup: require.resolve('./global-setup'),
};
export default config;
again you don't have to write code to use the session-storage at each test level, you can use - use attribute of Playwright configuration as below:
// playwright.config.ts
import { PlaywrightTestConfig } from '#playwright/test';
const config: PlaywrightTestConfig = {
globalSetup: require.resolve('./global-setup'),
use: {
// Tell all tests to load signed-in state from 'storageState.json'.
storageState: 'storageState.json'
}
};
export default config;
Seems like you are trying to use the same context in both tests, could that be a problem?
can you please try with isolated context and page for each tests?
Also please check if it make sense to use session storage at test level instead of context-
test.use({ storageState: './storage/admin.json' })
Update about the tests-
General structure of tests would be -
test.describe('New Todo', () => {
test('Test 1', async ({context, page }) => {});
test('Test 2', async ({context, page }) => {});
});
I looked into the source code of playwright and found these two lines which show the error message you see.
assert(!(c.expires && c.expires < 0 && c.expires !== -1), 'Cookie should have a valid expires, only -1 or a positive number for the unix timestamp in seconds is allowed');
assert(!(c.expires && c.expires > 0 && c.expires > kMaxCookieExpiresDateInSeconds), 'Cookie should have a valid expires, only -1 or a positive number for the unix timestamp in seconds is allowed');
The kMaxCookieExpiresDateInSeconds is defined as 253402300799.
So basically the cookie that you captured could breach one of above rules. In my case it's that the expiry of a cookie is greater than this figure :).
refer to source code - https://github.com/microsoft/playwright/blob/5fd6ce4de0ece202690875595aa8ea18e91d2326/packages/playwright-core/src/server/network.ts#L53

Testing VSCode Extension with mocha and puppeteer behaves strangely

I'm writing test code for VS Code Extension with mocha and puppeteer.
This code behaves oddly.
This test will change the result without editing the code.
Sometimes test is failed because timeout of const e = await global.page.waitForSelector("iframe", { timeout: 10000 });, and sometimes it succeeds.
Changing the value of the slowMo option of puppeteer.launch() after several timeouts may result in a successful test. (not every time)  
How can I make this stable?
describe("test", () => {
before(async () => {
global.browser = await puppeteer.connect({
browserURL: 'http://127.0.0.1:9229',
defaultViewport: null,
slowMo: 10
});
global.page = (await global.browser.pages())[0];
});
after(async () => {
if (global.page) {
await global.page.close();
}
if (global.browser) {
global.browser.disconnect();
}
});
describe("open file", () => {
before(async () => {
// open file with my custom editor
const uri = Uri.file(path.join(__dirname, "test.pdf"));
await commands.executeCommand("vscode.open", uri);
// get editor's dom content
const e = await global.page.waitForSelector("iframe", { timeout: 10000 });
const ec = await editor.contentFrame();
const ee = await editorFrame.waitForSelector("iframe#active-frame", { timeout: 10000 });
const eec = await editorContent.contentFrame();
global.dom = eec;
});
after(async () => {
await commands.executeCommand("workbench.action.closeActiveEditor");
});
it("should have x", async () => {
const x = await global.doc.waitForSelector("#x", { timeout: 5000 });
assert.ok(x);
});
});
});

Conditionally Execute test() in Flutter

When using the Flutter test and drive options, can we control the execution of certain test based on the results from the previous ones ? We have a skip option in the test. However, I was unable to find anyway to check whether a previous test passed in the program. For example :
void main() {
group('Group A', () {
FlutterDriver driver;
// Connect to the Flutter driver before running any tests.
setUpAll(() async {
driver = await FlutterDriver.connect();
});
// Close the connection to the driver after the tests have completed.
tearDownAll(() async {
if (driver != null) {
driver.close();
}
});
test('Test A', () async {
});
test('Test B', () async {
});
test('Test C', () async {
});
});
}
My question is , how can I skip the execution of B and C if A failed and how can I skip the execution of group B id group A tests failed ?
There doesn't appear to be an explicit way to declare test dependencies, but you could keep track of which tests have passed, and use that information to skip subsequent tests conditionally, e.g.
final passed = <String>{};
test("a", () {
expect(1 + 1, 3);
passed.add("a");
});
test("b", () {
expect(2 + 2, 5);
}, skip: !passed.containsAll(["a"]));

how to prevent Chrome headless from loading images

I am running a test in headless chrome and part of it I want to prevent the browser from loading the images on the page, the page must be a data url and not a normal page.
I am using headless chrome with the next start command:
chrome --headless --remote-debugging-port=9222
I had created the next test to demonstrate what I am trying to achieve.
but nothing works...
const CDP = require('chrome-remote-interface');
const fs = require('fs');
CDP(async(client) => {
const {
Page,
Network
} = client;
try {
await Page.enable();
await Network.enable();
await Network.emulateNetworkConditions({
offline: true,
latency: 0,
downloadThroughput: 0,
uploadThroughput: 0
});
await Page.navigate({
url: "data:text/html,<h1>The next image should not be loaded</h1><img src='http://via.placeholder.com/350x150'>"
});
await Page.loadEventFired();
const {
data
} = await Page.captureScreenshot();
fs.writeFileSync((+new Date()) + '.png', Buffer.from(data, 'base64'));
} catch (err) {
console.error(err);
} finally {
await client.close();
}
}).on('error', (err) => {
console.error(err);
});
You can block images using this flag.
It works on canary and stable.
chrome --headless --remote-debugging-port=9222
--blink-settings=imagesEnabled=false
With puppeteer you can use the args option for passing the blink-settings argument
const browser = await puppeteer.launch({
args: [
'--blink-settings=imagesEnabled=false'
]
});
If you are using Puppeteer, you can use the code below:
await page.setRequestInterception(true);
page.on('request', (request) => {
if (request.resourceType() === 'image') request.abort();
else request.continue();
});
From: https://github.com/puppeteer/puppeteer/blob/main/examples/block-images.js