dkornishev / dherkin

Cucumber gherkin runtime for dart
BSD 2-Clause "Simplified" License
8 stars 5 forks source link

Add ability to load gherkin via http #13

Open dkornishev opened 10 years ago

dkornishev commented 10 years ago

Drop assumptions of file-system and add ability to run remote gherkin

Goutte commented 10 years ago

Right now, I get IsolateSpawnException: 'spawnFunction is not supported from a dom-enabled isolate. Please use spawnUri instead.' when I handle a GherkinParserTask with a Worker.

Goutte commented 10 years ago

This is linked to the first issue of Worker : https://github.com/Dreckr/Worker/issues/1

Goutte commented 10 years ago

Also, Gherkin feature files should be packed / unpacked to only have one transferred file.

The archive lib springs to mind.

dkornishev commented 10 years ago

Not sure what you mean.

I got double output (execution?) for scenario outline with a missing step

2014-06-22 12:10 GMT-04:00 Antoine Goutenoir notifications@github.com:

Also, Gherkin feature files should be packed / unpacked to only have one transferred file.

The archive https://pub.dartlang.org/packages/archive lib springs to mind.

— Reply to this email directly or view it on GitHub https://github.com/dkornishev/dherkin/issues/13#issuecomment-46785074.

Goutte commented 10 years ago

I mean that the server serving the static gherkin files should tarball them into one compressed file and that dherkin on client-side should be able to receive that compressed file and run the multiple features. Of course, it should also be able to receive one uncompressed gherkin feature file.

As for double output, i'm not sure what you mean, as I've got :


$ dart -c run.dart ./gherkin/everything.feature
I run some background
Компрессия! {table: []}
УРА!
Everything Works [works]
I run some background
I run some background
Columns are working hello world
COLUMN 2 {table: []} world
Columns are working goodbye world
Table1 {table: [{column1: A, column2: B, column3: C, column4: D}, {column1: E, column2: F, column3: G, column4: H}]} []
Table2 {table: []} []
COLUMN 2 {table: []} world
Table4 {table: []} []

Feature: Making sure that parser works # ./gherkin/everything.feature:2

    Scenario: Background # ./gherkin/everything.feature:4
        I run some background    # ./gherkin/everything.feature:5

    Scenario: Parser is working # ./gherkin/everything.feature:8
        parser is working    # ./gherkin/everything.feature:9
        I run dherkin    # ./gherkin/everything.feature:10
Exception: блин
#0      i_run_dherkin (file:///home/antoine/Code/FORKS/dherkin/example/run.dart:21:3)
#1      _LocalObjectMirror.invoke (dart:mirrors-patch/mirrors_impl.dart:236)
#2      findStepRunners.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (file:///home/antoine/Code/FORKS/dherkin/lib/dherkin_core.dart:39:25)
#3      Scenario.execute.<anonymous closure> (file:///home/antoine/Code/FORKS/dherkin/lib/src/gherkin_model.dart:172:31)
#4      _rootRunUnary (dart:async/zone.dart:730)
#5      _RootZone.runUnary (dart:async/zone.dart:864)
#6      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:488)
#7      _Future._propagateToListeners (dart:async/future_impl.dart:571)
#8      _Future._completeWithValue (dart:async/future_impl.dart:331)
#9      _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:393)
#10     _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:23)
#11     _asyncRunCallback (dart:async/schedule_microtask.dart:32)
#12     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:128)

        the phase of the moon is "favorable"     # ./gherkin/everything.feature:11
        everything "works"   # ./gherkin/everything.feature:12

    Scenario: Background # ./gherkin/everything.feature:4
        I run some background    # ./gherkin/everything.feature:5

    Scenario: Outline Some examples # ./gherkin/everything.feature:14
        I read <column1>     # ./gherkin/everything.feature:15
        I evaluate <column2>     # ./gherkin/everything.feature:16

    Scenario: Outline Some examples # ./gherkin/everything.feature:14
        I read <column1>     # ./gherkin/everything.feature:15
        I evaluate <column2>     # ./gherkin/everything.feature:16

    Scenario: Background # ./gherkin/everything.feature:4
        I run some background    # ./gherkin/everything.feature:5

    Scenario: Tables # ./gherkin/everything.feature:23
        I have a table   # ./gherkin/everything.feature:24
        I am a step after the table  # ./gherkin/everything.feature:28
        I am a table step executed   # ./gherkin/everything.feature:29
        everything works just fine   # ./gherkin/everything.feature:33
-------------------
Scenarios passed: 2
Scenarios failed: 1

-------------------
Failed features : 1

ALL DONE

@StepDef("I am a table step executed")
i_am_a_table_step(ctx, params, { column1, column2, column3, column4 }) {
  // todo 
}

@StepDef("the phase of the moon is \"(\\w+?)\"")
the_phase_of_the_moon(ctx, params) {
  // todo 
}
dkornishev commented 10 years ago

I refactored the calling of the steps. Boilerplate generation is not right yet though.

2014-06-22 12:16 GMT-04:00 Danil Kornishev danil.kornishev@gmail.com:

Not sure what you mean.

I got double output (execution?) for scenario outline with a missing step

2014-06-22 12:10 GMT-04:00 Antoine Goutenoir notifications@github.com:

Also, Gherkin feature files should be packed / unpacked to only have one

transferred file.

The archive https://pub.dartlang.org/packages/archive lib springs to mind.

— Reply to this email directly or view it on GitHub https://github.com/dkornishev/dherkin/issues/13#issuecomment-46785074.

Goutte commented 10 years ago

I configured a small ForceServer to serve a tar of my folder of features.

tar.bz2 is one breath away.

Maybe this'll be of interest to you.

library aego_force_server;

import 'dart:io';

import 'package:args/args.dart';
import 'package:force/force_serverside.dart';
import 'package:archive/archive.dart';

void main(args) {
  var parser = new ArgParser();
  parser.addOption('port', abbr: 'p', defaultsTo: '8282', help: "Port for force_server");
  parser.addOption('host', abbr: 'o', defaultsTo: 'localhost', help: "Domain name of the host");
  parser.addOption('trials', abbr: 't', defaultsTo: './jungle', help: "Directory of the gherkin trials");
  parser.addFlag('verbose', abbr: 'v', defaultsTo: false, negatable: false);
  parser.addFlag('help',abbr: 'h', negatable: false);
  var argMap = parser.parse(args);
  if (argMap["help"] == true) {
    print(parser.getUsage());
    return;
  }

  ForceServer fs = new ForceServer(
      port: int.parse(argMap['port']),
      startPage: 'index.html',
      host: argMap['host']
  );

  fs.start().then((_) {
    print("Force Server started");
    registerRoutes(fs, argMap);
    print("Routes registered");
  });

}

void registerRoutes(ForceServer fs, ArgResults argMap) {
  /// JUNGLE TRIALS ----------------------------------------------------------
  var jungleTrialsDir = new Directory(argMap['trials']);
  fs.serve("/jungle/trials.tar").listen((request) {
    String targetPath = argMap['trials']+"/trials.tar";
    print("Serving ${targetPath}");
    List<File> jungleTrials = collectJungleTrials(jungleTrialsDir);
    generateTarSync(targetPath, jungleTrials);
    fs.serveFile(targetPath, request);
  });
  /// ------------------------------------------------------------------------
}

/// Collects `.feature` files [inDirectory] and sub-directories
List<File> collectJungleTrials(Directory inDirectory) {
  List<File> jungleTrials = [];

  // Recursively list directory contents, not following symbolic links.
  for (FileSystemEntity entity in inDirectory.listSync(recursive: true, followLinks: false)) {
    // Keep only .feature files
    if (entity is File && entity.path.endsWith('.feature')) {
      jungleTrials.add(entity);
    }
  }

  return jungleTrials;
}

/// Creates synchronously a tar file in [targetPath] containing all [files].
TarFile generateTarSync(String targetPath, List<File> files) {
  TarEncoder tarEncoder = new TarEncoder();
  Archive archive = new Archive();
  for (File trial in files) {
    print("  Add ${trial.path}, ${trial.lengthSync()} bytes");
    ArchiveFile archiveFile = new ArchiveFile(trial.path, trial.lengthSync(), trial.readAsBytesSync())
      ..mode    = 644
      ..ownerId = 0
      ..groupId = 0
      ..lastModTime = trial.lastModifiedSync().difference(new DateTime.fromMillisecondsSinceEpoch(0)).inSeconds;
    archive.addFile(archiveFile);
  }
  List<int> encoded = tarEncoder.encode(archive);
  File out = new File(targetPath);
  out.createSync(recursive: true);
  out.writeAsBytesSync(encoded);
}