Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Test with CSV download fails on Windows if Chromium (or any browser or tab) is open #30687

Closed
Kazmenko-Vasyl opened this issue May 7, 2024 · 2 comments

Comments

@Kazmenko-Vasyl
Copy link

Kazmenko-Vasyl commented May 7, 2024

Version

Version 1.43.1

Steps to reproduce

CSVbugPlaywright
I'm pretty sure something is going wrong with Playwright here, this test works perfectly well on macOS every single time, and it does work on Windows in headless mode if I don't open any tabs or windows, but as soon as I run this test with runner and Browser opens this test just timeouts every single time
if I run the test in headless mode but open Chrome and start doing something test fails as well

It can pass the very first time when browser opens, but then fails again, if i just expand Chromium before download it fails the test

It looks like something is wrong with the download event when the browser is opened


test('Check CSV file not empty', async ({ page }) => {
    const pm = new PageManager(page);
    test.slow();
    await pm.copilotLoginPage().copilotLoginPage('KAZMENKOUIAUTOMATION', 'Kazmenko19967!');
    await pm.copilotLoginPage().navigateTo('Customers');
    await pm.copilotLoginPage().searchForPartner('Kazmenko');
    await page.waitForTimeout(10000);
    await pm.copilotLoginPage().exportCustomers();

    const [download] = await Promise.all([
        page.waitForEvent('download'),
    ]);
    const saveDirectory = 'ExportFiles';
    const fileName = 'file1232.csv';
    const filePath = `${saveDirectory}/${fileName}`;

    await download.saveAs(filePath);

    const csvText = readFileSync(filePath, 'utf-8');
    console.log('Before parsing CSV');

    // Parse the CSV data asynchronously
    const records: CSVRow[] = await new Promise((resolve, reject) => {
        parse(csvText, {
            columns: true
        }, (err, output) => {
            if (err) {
                reject(err);
            } else {
                resolve(output);
            }
        });
    });

    console.log('After parsing CSV');
    console.log(records);

    // Verify Customer Id field is not empty for each row
    const emptyCustomerIdRows = records.filter(record => !record['Customer ID']);

    if (emptyCustomerIdRows.length > 0) {
        console.error('Customer Id field is empty for the following rows:');
        console.error(emptyCustomerIdRows);
        expect(emptyCustomerIdRows).toHaveLength(0);
    } else {
        console.log('Customer Id field is not empty for all rows.');
    }
});

interface CSVRow {
  [key: string]: string; // Assuming all values in the CSV are strings
}

Expected behavior

Download event should pass when I run the test with Playwright runner in VS CODE

Actual behavior

Download event timeout error when browser is opened

Additional context

These is just methods

import { test, expect, Page, Locator } from '@playwright/test';

export class LoginPage {
    readonly page: Page;

    constructor(page: Page) {
        this.page = page;
    }

    async copilotLoginPage(username: string, password: string) {
        const submitButton = this.page.locator('#kc-login[type="submit"]');
        const headerDisplay = this.page.locator('[class="page-title hide-gt-sm ng-binding"]');
        const loginForm = this.page.locator('[class="cc-form-table cc-login"]');
        await loginForm.getByRole('textbox', {name: 'username'}).fill(username)
        await loginForm.getByRole('textbox', {name: 'password'}).fill(password)
        await submitButton.click();
        await this.page.waitForLoadState('networkidle');
        await expect(headerDisplay).toBeVisible();
    }

    async navigateTo(pageName: string) {
        const sidebarMenu = this.page.locator('a.nav-btn span');
        const link = await sidebarMenu.getByText(pageName)
        await link.click();
        await this.page.waitForLoadState('networkidle');
        await this.page.waitForSelector(`h1.page-title.hide-gt-sm.ng-binding:has-text("${pageName}")`);
    }

    async searchForPartner(partnerName: string) {
        const searchInput = this.page.locator('[placeholder="Search"][aria-hidden="false"]');
        
        await searchInput.fill(partnerName);
        await searchInput.press('Enter');
    }

    async selectPartner(partnerId: string) {
        const partnerLink = this.page.locator(`tr a:has-text("${partnerId}")`);

        await partnerLink.click();
        await this.page.waitForSelector('div.page-title-section.page-title');
    }

    async exportCustomers() {
        // Locate the parent div containing md-select
        const exportButton = await this.page.locator('.export-button.md-button');
        await exportButton.click();
    
        // Assuming exportButtonCSV was supposed to be assigned to exportButtonSV
        const exportButtonSV = await this.page.locator('md-menu-item[ng-show="!table.customDownload"] a.md-button.md-ink-ripple .ng-scope:has-text("Export Report as CSV")');
        await exportButtonSV.click();
    }
    
}

Environment

System: Windows 11, version 23H2
VS CODE
Chromium only
@mxschmitt
Copy link
Member

mxschmitt commented May 7, 2024

The test above looks racy, try rewriting it like that, then it should work. I expect exportCustomer to trigger the download:

const downloadPromise = page.waitForEvent('download');    
await pm.copilotLoginPage().exportCustomers();
const download = await downloadPromise;

See here about our guide for handling downloads: https://playwright.dev/docs/downloads

The reason why its flaky is that the download is happening before you wait for the download event. When rewriting with the code above you wait for the download event, start the download (export the customer) and then actually await the download event.

@mxschmitt
Copy link
Member

Closing as part of the triage process since it seemed stale. Please create a new issue with a detailed reproducible or feature request if you still face issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants