2016-04-12 6 views
0

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

Я использую angular2-seed и хочу запустить тесты проталкивателя в режиме безглавых с помощью Xvfb. Я не хочу, чтобы сервер Xvfb работал постоянно (это сервер сборки), поэтому вместо этого я хотел бы раскрутить службу Xvfb, сделать это, и затем «изящно» закрыть Xvfb. В изоляции эти задачи работают нормально, однако я ударил стену, когда дело доходило до их добавления в настройку сборки gulp.

Вот задача в gulpfile:

gulp.task('e2e.headless', (done: any) => 
    runSequence('start.xvfb', 
       'protractor', 
       'stop.xvfb', 
       done)); 

Задачи сами загружаются через файлы задачи индивидуальной машинописи, то есть:

import {runProtractor} from '../../utils'; 

export = runProtractor 

А вот моя (последняя) утилита самих файлов.

protractor.ts

import * as util from 'gulp-util'; 
import {normalize, join} from 'path'; 
import {ChildProcess} from 'child_process'; 

function reportError(message: string) { 
    console.error(require('chalk').white.bgRed.bold(message)); 
    process.exit(1); 
} 

function promiseFromChildProcess(child: ChildProcess) { 
    return new Promise(function (resolve:() => void, reject:() => void) { 
    child.on('close', (code: any) => { 
     util.log('Exited with code: ', code); 
     resolve(); 
    }); 
    child.stdout.on('data', (data: any) => { 
     util.log(`stdout: ${data}`); 
    }); 

    child.stderr.on('data', (data: any) => { 
     util.log(`stderr: ${data}`); 
     reject(); 
    }); 
    }); 
} 

export function runProtractor(): (done:() => void) => void { 
    return done => { 
    const root = normalize(join(__dirname, '..', '..', '..')); 
    const exec = require('child_process').exec; 

    // Our Xvfb instance is running on :99 
    // TODO: Pass this in instead of hard-coding 
    process.env.DISPLAY=':99'; 
    util.log('cwd:', root); 

    let child = exec('protractor', { cwd: root, env: process.env}, 
     function (error: Error, stdout: NodeBuffer, stderr: NodeBuffer) { 
     if (error !== null) { 
      reportError('Protractor error: ' + error + stderr); 
     } 
     }); 
    promiseFromChildProcess(child).then(() => done()); 
    }; 
} 

xvfb_tools.ts

import * as util from 'gulp-util'; 

const exec = require('child_process').exec; 

function reportError(message: string) { 
    console.error(require('chalk').white.bgRed.bold(message)); 
    process.exit(1); 
} 

export function stopXvfb() { 
    return exec('pkill -c -n Xvfb', 
     function (error: NodeJS.ErrnoException, stdout: NodeBuffer, stderr: NodeBuffer) { 
      if (error !== null) { 
       reportError('Failed to kill Xvfb. Not really sure why...'); 
      } else if (stdout.toString() === '0') { 
       reportError('No known Xvfb instance. Is it running?'); 
      } else { 
       util.log('Xvfb terminated'); 
      } 
     }); 
} 

export function startXvfb() { 
    return exec('Xvfb :99 -ac -screen 0 1600x1200x24', 
     function (error: NodeJS.ErrnoException, stdout: NodeBuffer, stderr: NodeBuffer) { 
      if (error !== null && error.code !== null) { 
       reportError('Xvfb failed to start. Err: ' + error.code + ', ' + error + ', ' + stderr); 
      } 
     }); 
} 

Я чувствую, что я, вероятно, вокруг домов в создании обещание от моего exec child_process, однако ранние взаимодействия кода не выполнялись it, so ... Обратите внимание, что журнал отладки, который должен выводиться в runProtractor(), отображающий корневую директорию, никогда не вызывается, поэтому я совершенно уверен, что здесь есть проблема с асинхронным воспроизведением. Вот вывод из задачи:

[00:47:49] Starting 'e2e.headless'... 
[00:47:49] Starting 'start.xvfb'... 
[00:47:49] Finished 'start.xvfb' after 12 ms 
[00:47:49] Starting 'protractor'... 
[00:47:49] Finished 'protractor' after 5.74 ms 
[00:47:49] Starting 'stop.xvfb'... 
[00:47:49] Finished 'stop.xvfb' after 11 ms 
[00:47:49] Finished 'e2e.headless' after 38 ms 
[00:47:49] Xvfb terminated 

Может кто-нибудь меня прямо посадить/направить меня в правильном направлении?

ответ

0

Благодаря Людовику из команды angular2-seed!

Ошибка заключалась в том, что не вызывал функцию runProtractor из класса обертки, то есть export = runProtractor(). Как только это было отмечено, я мог бы затем удалить ненужную функцию обертки, а также promFromChildProcess, которые были отвлекающими.

Последняя задача была только анонимная функцией, которая принимает глоток обратного вызова «Done», который вызывается при выходе:

function reportError(message: string) { 
    console.error(require('chalk').white.bgRed.bold(message)); 
    process.exit(1); 
} 

export = (done: any) => { 
    const root = normalize(join(__dirname, '..', '..', '..')); 
    const exec = require('child_process').exec; 

    process.env.DISPLAY=':99'; 
    util.log('cwd:', root); 

    exec('protractor', { cwd: root, env: process.env}, 
     function (error: Error, stdout: NodeBuffer, stderr: NodeBuffer) { 
     if (error !== null) { 
      reportError('Protractor error: ' + error + stderr); 
     } else { 
      done(); 
     } 
     }); 
} 
0

Вам необходимо добавить функцию обратного вызова к вашей задаче gulp и вызвать функцию cb после завершения всех задач runSequence.

gulp.task('e2e.headless', (cb) => 
runSequence('start.xvfb', 
    'protractor', 
    'stop.xvfb', 
    (err) => 
     if (err) { 
      console.log(err.message); 
     } else { 
      console.log("Build finished successfully"); 
     } 
     cb(err); 
    }); 
}); 
+0

это не то, что 'done' для в моей текущей задаче? – GMeister

+0

Да, Выполнено? – Vish

+0

Это не было, см. Мой ответ за то, почему - спасибо – GMeister

 Смежные вопросы

  • Нет связанных вопросов^_^