1

Here is my code

const {test, expect} = require('@playwright/test')
const { generateRandomUser } = require('../helpers')

const firstUser = generateRandomUser();
const secondUser = generateRandomUser();
const users = [firstUser, secondUser];

// parametrized test
users.forEach(user => {
  console.log('USER', user);
  const { username, email, password } = user;
  test(`should register ${username}`, async ({ page }) => {
    await page.goto('https://conduit.mate.academy/user/register');

    await page.getByPlaceholder('Username').fill(username);
    await page.getByPlaceholder('Email').fill(email);
    await page.getByPlaceholder('Password').fill(password);
    await page.getByRole('button', { name: 'Sign up' }).click();

    await expect(page.locator(`a.nav-link[href='/profile/${username}']`)).toBeVisible();

    await page.pause();
  });
});

Here is the generateRandomUser function

const { faker } = require('@faker-js/faker');

exports.generateRandomUser = () => {
  const random = Math.random().toString().slice(2, 6);
  let username = faker.lorem.word() + '_' + random;
  username = username.toLowerCase()
  const email = username + '@gmail.com';
  const password = faker.internet.password();

  return {
    username,
    email,
    password
  }
}

So, basically I just want to have a good grasp of Playwright and just decided to try parametrize test, but when I run them I get this error

Internal error: unknown test(s) in worker:
chromium > exploring_playwright.spec.js > should register officiis_0247

2 failed [chromium] › exploring_playwright.spec.js:12:3 › should register beatae_1183 ─────────────────── [chromium] › exploring_playwright.spec.js:12:3 › should register officiis_0247 ─────────────────

And moreover, when I use console.log() to see if the user was generated right I can see that in my console more than 2 outputs of users, which is strange, I guess this is the reason it fails but I have no idea how is it possible. I used this generateRandomUser() function for the previous tests and also for the Sign Up Page, like here and everything works fine.

const {test, expect} = require('@playwright/test')
const { generateRandomUser, registerNewUser } = require('../../helpers')

test.beforeEach(async ({page}) => {
  await page.goto('https://conduit.mate.academy/user/register');
})

test('should register a new user', async ({page}) => {
  const {username, email, password} = generateRandomUser();

  await page.getByPlaceholder('Username').fill(username);
  await page.getByPlaceholder('Email').fill(email);
  await page.getByPlaceholder('Password').fill(password);
  await page.getByRole('button', { name: 'Sign up' }).click();

  await expect(page.locator(`a.nav-link[href='/profile/${username}']`)).toBeVisible();
})

I tried to use resources like Youtube videos and documentation. Here is the references (photos) this one and this one

I asked ChatGPT, tried to add describe block, tried to use test.describe.parallel, but it didn't do much.

This option is also incorrect

for(let i = 0; i < 2; ++i) {
  const {username, email, password} = generateRandomUser();
  console.log(username, email, password)

  test(`should register ${username}`, async ({ page }) => {
    await page.goto('https://conduit.mate.academy/user/register');

    await page.getByPlaceholder('Username').fill(username);
    await page.getByPlaceholder('Email').fill(email);
    await page.getByPlaceholder('Password').fill(password);
    await page.getByRole('button', { name: 'Sign up' }).click();

    await expect(page.locator(`a.nav-link[href='/profile/${username}']`)).toBeVisible();

    await page.pause();
  });
}

I still see 6 users created instead of 2.

Stepash
  • 13
  • 5

3 Answers3

1

I beleive you might be running the tests on several workers which cause firstUser and secondUser to be generated for each worker. If you run the test with a single worker, the test will most likely run as expected:

// playwright.config
export default defineConfig({
    workers: 1
}

Several workers

If you want to run the test on several workers, you could set a seed to persist the faker generated data, example of implementation:

import {faker} from '@faker-js/faker/locale/nb_NO'

const {test, expect} = require('@playwright/test')
const { generateRandomUser } = require('../helpers')

const firstUser = generateRandomUser(11);
const secondUser = generateRandomUser(22);
const users = [firstUser, secondUser];

// parametrized test
for(const user of users) {
  const { username, email, password, seed } = user;
  faker.seed(seed)
  test.only(`should register ${username}`, async ({ page }) => {
    // Your code
  });
};
const { faker } = require('@faker-js/faker');

exports.generateRandomUser = (seed) => {
  faker.seed(seed)
  // For the seed to work, you cannot use math.random, but faker generated number
  // const random = Math.random().toString().slice(2, 6); 

  const random = faker.number.int({ min: 100, max: 100000 })
  let username = faker.lorem.word() + '_' + random;
  username = username.toLowerCase()
  const email = username + '@gmail.com';
  const password = faker.internet.password();

  return {
    username,
    email,
    password,
    seed
  }
}
candre
  • 593
  • 3
  • 8
  • Yeah, it was a nice guess, thank you but it still doesn't solve my problem, more users created module.exports = defineConfig({ testDir: './tests/', timeout: 10 * 1000, expect: { timeout: 3 * 1000, }, /* Run tests in files in parallel */ fullyParallel: true, forbidOnly: !!process.env.CI, /* Retry on CI only */ // retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ workers: 1, I changed workers to 1 and tried to replace fullyParallel value, but no – Stepash Jul 06 '23 at 11:12
  • Weird, I ran you code myself with 1 worker, and it worked. Did you try my second option by adding a seed? – candre Jul 06 '23 at 11:25
  • And, as pointed out in another post, you did replace the forEach with for .. of ? – candre Jul 06 '23 at 11:27
  • Yeah, with seed everything is fine now, can you please explain how seed did it? Why initial code was wrong? Ans thank you so much – Stepash Jul 06 '23 at 11:45
  • And can you please provide some resources to read about this faker.seed because I'm having tough times finding something good? – Stepash Jul 06 '23 at 11:49
  • Each time `generateRandomUser()` is called, new random data is generated. Each time a new fixture is created `generateRandomUser()` is called so it results in different data in each fixture. By setting a unique seed on **each** user case the same data is returned. More about it here: https://fakerjs.dev/guide/usage.html#reproducible-results – candre Jul 06 '23 at 11:53
  • Thanks, if you don't mind can you please clarify for me why the initial code without seed failed? And as far as I understood this seed we use to chain random data to some value and use it until we don't rewrite it with another seed, am I right? And I wanted to play with the code, because it's sign up page and I don't have access to the site, so I can't clear the database, so hardcoded values like generateRandomUser(11) works just once, I created random function that return Math.floor(Math.random() * max); and passed this result as a argument to the function, but it doesn't work. – Stepash Jul 06 '23 at 12:02
  • I dont know the tech details, but I beleive the seed sets a state of the rng, so it returns the same each time until you use a different seed value. Your test failed with error `Internal error: unknown test(s) in worker` - the name of the test, `should register ${username}`, is from a `generateRandomUser()` call and when running the test, `generateRandomUser()` is called a second time, providing different data than the one used in test name. – candre Jul 06 '23 at 12:52
  • I'm unfortunately not sure how to solve your issue with wanting different data each run. Maybe by parametrizing the entire project instead of the tests, but I have not tried it. – candre Jul 06 '23 at 12:56
  • Ok, thank you anyway, have a nice day. – Stepash Jul 06 '23 at 13:24
  • Thanks @candre, +1 learnt something more today about faker library! – Vishal Aggarwal Jul 06 '23 at 16:16
0

I tried your code in base form and it is working fine

const {test, expect} = require('@playwright/test')
// const { generateRandomUser } = require('../helpers')

const firstUser = "firstUser";
const secondUser = "secondUser";
const users = [firstUser, secondUser];

// parametrized test
users.forEach(user => {
  console.log('USER', user);
  test(`should register ${user}`, async ({ page }) => {
    console.log(user);
  });
});

Output:

 $ npx playwright test example3.spec.ts

USER firstUser
USER secondUser

Running 2 tests using 1 worker

USER firstUser
USER secondUser
  ✓  1 example3.spec.ts:11:3 › should register firstUser (109ms)
firstUser
  ✓  2 example3.spec.ts:11:3 › should register secondUser (53ms)
secondUser

  2 passed (3.7s)

and I'm on Playwright version 1.35.1

I think generateRandomUser does not have any await, or is that function is async or not?

seems like your issue here is with username not getting defined till it is called which is failing the tests.

tushi43
  • 60
  • 1
  • 6
  • No, generateRandomUser doesn't return a promise, so I didn't mark it as asynchronous. I also tried just simple parametrize with just numbers and it worked fine, but here I for some reason see additional users being created – Stepash Jul 06 '23 at 09:08
0

ForEach loop doesn't await for the promises.

Use for- of loop instead:

async function printFiles () {
  const files = await getFilePaths();

  for await (const file of files) {
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  }
}

Reference: https://stackoverflow.com/a/37576787

Vishal Aggarwal
  • 1,929
  • 1
  • 13
  • 23