Jasmine: циклические тесты не запускаются, если они асинхронны

Я работаю над реализацией теста, который читает список файлов из заданного каталога. Затем список сверяется с объектом Map, который использует имена файлов в качестве ключей. Если совпадение найдено, я хочу выполнить некоторые тесты, если нет, пропустить файл и перейти к следующему.

У меня работает тест, если я просто беру один объект с карты, но он терпит неудачу, когда я пытаюсь зациклиться. Я хочу запускать тесты, перебирая несколько файлов.

Это кажется проблемой только в том случае, если в моих тестах есть асинхронные вызовы. Используя полностью синхронный цикл, я могу заставить его работать нормально. Вот пример синхронного цикла (Я понимаю, что это очень надуманный пример, но он работает так, как ожидалось):

describe('a test', () => {
  const list = ['a', 'b', 'c'];

  const test = (x) => {
    describe(`should run ${x}`, () => {
        beforeAll(async () => {
            console.info('beforeAll');
        });

        beforeEach(async () => {
            console.info('beforeEach');
        });

        for(let i = 0; i < 2; i++) {
          it(`should log iteration ${i}`, async () => {
            console.info(x, i);

            expect(i).toBeTruthy();
          });
        }
    });
  }

  for (let i = 0; i < list.length; i++) {
    test(list[i]);
  }
});

Вывод из приведенного выше фрагмента говорит о том, что он работает нормально: Jasmine: циклические тесты не запускаются, если они асинхронны

Однако этот же шаблон не работает, если он асинхронный. На самом деле, насколько я могу судить, вложенное описание в test даже не работает. Я записал переменную project в консоль, чтобы видеть, что она вызывается, но оператор logging in... в beforeAll вообще не выполняется. Кажется, что он просто пропускает прямо через него. Как мне заставить это работать с async/await?

describe('Import Project', () => {
  const _page = new PageFactory();
  const utils = new Utils();
  const projPath = browser.params.projPath;

  let projectGuid: string;

  const test = (project) => {
    describe(`importing ${project.name}`, () => {
        beforeAll(async () => {
            console.info('logging in...'); //not getting executed for some reason
            await _page.loginPage.login(browser.params.username, browser.params.password);

            // import
            await _page.projectsPage.importProject(projectPath + project.filename)
                .withImportType(project.importType)
                .withProjectName(project.projectName)
                .inEnvironment(project.environment)
                .import();

            projectGuid = await utils.extractGuid();
        });

        afterEach(async () => {
            await _page.designerPage.navigateTo(projectGuid);
        });

        for(let i = 0; i < project.operations.length; i++) {
            const operation = project.operations[i];

            it(`should run ${operation.name} successfully`, async () => {
                await runOperation(operation.name);

                const status = await _page.operationLogsPage.getStatus(operation.outcomeTarget);
                expect(status).toEqual(operation.expectedStatus);
            });
        }
    });
  }

  utils.getProjects().then(projects => {
    // projects is a string[] of filenames
    // that are returned using fs.readdir()
    for (let i = 0; i < projects.length; i++) {
        const myProject = projectMap.get(projects[i]);

        if (myProject) {
            test(myProject);
        }
    }
  });
});

Результат от этого просто Executed 0 of 0 specs SUCCESS in 0.003 sec.

Я не понимаю, чем это отличается от ручного написания всех этих вложенных блоков описания. Если бы я выписал каждый из них, он бы работал нормально, но по какой-то причине в цикле он не хочет работать. Есть идеи?

Для справки, я также пробовал ждать test. Это тоже не сработало.

tehbeardedone 10.04.2019 23:55

цикл for не ожидает внутри себя асинхронной процедуры. это связано с этим вопросом stackoverflow.com/questions/11488014/…

SET 11.04.2019 00:10

Этот ответ предполагает несколько вещей, которые не работают. .forEach(async p => { // do stuff } терпит неудачу с тем же результатом. Помещение цикла внутри асинхронной функции, такой как async function something() { for(..) { await test(project) } }, тоже не работает.

tehbeardedone 11.04.2019 00:53
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
168
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не мог понять, как заставить это работать так, как я хотел. Вместо этого я решил использовать узел child_process.execSync и таким образом перебирал каждый файл. Это не идеально, но это работает. Занимает немного больше времени, так как каждый файл, который я хочу запустить для тестов, создает новый сеанс, но я устал пытаться заставить его работать по-другому.

Я запускаю скрипт, используя node ./path/to/test.js --baseUrl=http://<myUrl>

Вот соответствующая часть кода:

fs.readdir(projectsPath, (err, files) => {
  if (err) {
    throw new Error('Unable to scan directory: ' + err);
  }

  let i = 0;

  const next = () => {
    if (i < files.length) {
        const file = files[i];
        console.info('running tests on:', file);            

        const runCmd = `nodenv --exec "yarn run e2e:all ${baseUrl} --params.projectToImport=${file} --suite import_projects"`            

        // exec
        try {
            execSync(runCmd, { cwd: workingDir, stdio: 'inherit' },
                (error, stdout, stderr) => {
                    if (error) {
                        console.error(error);
                        return;
                    }

                    console.info(stdout);
                });
        } catch (err) {
            if (err.stderr) {
                console.info('stderr:', err.stderr.toString());
            }
        }

        // next iteration
        i++;
        next();
      }
  }

  next();
});

Другие вопросы по теме