harmonyc 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # Harmony Code
2
+
3
+ A simple model-based test design tool that generates Cucumber feature files.
4
+
5
+ ## Setup
6
+
7
+ You need to have Node.js installed. Then you can install Harmony Code in your project folder by:
8
+
9
+ ```bash
10
+ npm install harmonyc
11
+ ```
12
+
13
+ And then run it for all `.harmony` files in your `src` folder:
14
+
15
+ ```bash
16
+ harmonyc src/**/*.harmony
17
+ ```
18
+
19
+ This will generate `.feature` files next to the `.harmony` files.
20
+
21
+ ## Syntax
22
+
23
+ A `.harmony` file is a text file with a syntax that looks like this:
24
+
25
+ ```
26
+ Products API:
27
+ + Create:
28
+ + Anonymous:
29
+ - create product => error: unauthorized
30
+ + Admin:
31
+ - authenticate admin
32
+ - create product => product created
33
+ - Delete:
34
+ - delete product => product deleted
35
+ ```
36
+
37
+ Compiling this with `harmonyc` will generate this `.feature` file:
38
+
39
+ ```gherkin
40
+ Feature: products
41
+
42
+ Scenario: T1 - Products API - Create - Anonymous
43
+ When create product -- products
44
+ Then error: unauthorized -- products
45
+
46
+ Scenario: T2 - Products API - Create - Admin - Delete
47
+ When authenticate admin -- products
48
+ When create product -- products
49
+ Then product created -- products
50
+ When delete product -- products
51
+ Then product deleted -- products
52
+ ```
53
+
54
+ ### Indentation
55
+
56
+ The lines of a file are nodes of a tree. The tree is specified with the indentation of the lines, which is n times 2 spaces and a `+` or `-` with one more space. The `+` or `-` sign is considered to be part of the indentation.
57
+
58
+ ### Sequences and forks
59
+
60
+ `-` means a sequence: the node follows the previous sibling node and its descendants.
61
+
62
+ `+` means a fork: the node directly follows its parent node. All siblings with `+` are separate branches, they will generate separate scenarios.
63
+
64
+ ### Labels
65
+
66
+ Label are nodes that end with `:`. You can use them to structure your test design.
67
+ They are not included in the test case, but the test case name is generated from the labels.
68
+
69
+ ### Comments
70
+
71
+ Lines starting with `#` or `//` are comments and are ignored.
72
+
73
+ ### Steps
74
+
75
+ All other lines are steps. A step consists of an action, and one or more responses denoted by `=>`.
76
+ Actions will become `When` steps, and responses will become `Then` steps.
77
+
78
+
79
+ ## Running the tests
80
+
81
+ Currenlty `harmonyc` only compiles `.harmony` files to `.feature` files. To run the tests, you need to set up Cucumber or Specflow, depending on your environment.
82
+
83
+ ## License
84
+
85
+ MIT
package/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const compiler_1 = require("./compiler");
5
- if (process.argv.length < 3) {
5
+ if (process.argv.length < 3 || process.argv.includes('--help')) {
6
6
  console.error("Usage: harmonyc <input files glob pattern>");
7
7
  process.exit(1);
8
8
  }
package/compile.js CHANGED
@@ -6,7 +6,7 @@ const indent_1 = require("./util/indent");
6
6
  const model_1 = require("./model");
7
7
  const parser_1 = require("./parser");
8
8
  function compileFeature(name, src) {
9
- const root = (0, parser_1.parse)(src);
9
+ const root = (0, parser_1.parse)(src).setFeatureName(name);
10
10
  const tests = (0, model_1.makeTests)(root);
11
11
  const lines = [
12
12
  `Feature: ${name}`,
package/model.js CHANGED
@@ -14,6 +14,11 @@ class Branch {
14
14
  this.isFork = isFork;
15
15
  return this;
16
16
  }
17
+ setFeatureName(featureName) {
18
+ for (const child of this.children)
19
+ child.setFeatureName(featureName);
20
+ return this;
21
+ }
17
22
  addChild(child, index = this.children.length) {
18
23
  this.children.splice(index, 0, child);
19
24
  child.parent = this;
@@ -54,10 +59,10 @@ class Branch {
54
59
  }
55
60
  exports.Branch = Branch;
56
61
  class Step extends Branch {
57
- constructor(action = '', responses = [], children, isFork = false) {
62
+ constructor(action = '', responses = [], children, isFork = false, featureName = '') {
58
63
  super(children);
59
- this.action = new Action(action);
60
- this.responses = responses.map((response) => new Response(response));
64
+ this.action = new Action(action, featureName);
65
+ this.responses = responses.map((response) => new Response(response, featureName));
61
66
  this.isFork = isFork;
62
67
  }
63
68
  get phrases() {
@@ -66,6 +71,12 @@ class Step extends Branch {
66
71
  toGherkin() {
67
72
  return this.phrases.flatMap((phrase) => phrase.toGherkin());
68
73
  }
74
+ setFeatureName(featureName) {
75
+ this.action.setFeatureName(featureName);
76
+ for (const response of this.responses)
77
+ response.setFeatureName(featureName);
78
+ return super.setFeatureName(featureName);
79
+ }
69
80
  }
70
81
  exports.Step = Step;
71
82
  class State {
@@ -89,11 +100,15 @@ class Section extends Branch {
89
100
  }
90
101
  exports.Section = Section;
91
102
  class Phrase {
92
- constructor(text = '') {
103
+ constructor(text = '', featureName = '') {
93
104
  this.text = text;
105
+ this.featureName = featureName;
106
+ }
107
+ setFeatureName(featureName) {
108
+ this.featureName = featureName;
94
109
  }
95
110
  toGherkin() {
96
- return [`${this.kind === 'action' ? 'When' : 'Then'} ${this.text}`];
111
+ return [`${this.kind === 'action' ? 'When' : 'Then'} ${this.text} -- ${this.featureName}`];
97
112
  }
98
113
  }
99
114
  exports.Phrase = Phrase;
package/package.json CHANGED
@@ -1,28 +1,41 @@
1
- {
2
- "name": "harmonyc",
3
- "description": "Harmony Code - Test design compiler from high-level model to Gherkin",
4
- "version": "0.1.0",
5
- "author": "Bernát Kalló",
6
- "bin": {
7
- "harmonyc": "./cli.js"
8
- },
9
- "homepage": "https://github.com/harmony-ac/code#readme",
10
- "repository": {
11
- "type": "git",
12
- "url": "git+https://github.com/harmony-ac/code.git"
13
- },
14
- "bugs": {
15
- "url": "https://github.com/harmony-ac/code/issues"
16
- },
17
- "dependencies": {
18
- "fast-glob": "^3.3.2",
19
- "typescript-parsec": "0.3.4"
20
- },
21
- "license": "MIT",
22
- "keywords": [
23
- "unit test", "unit testing", "cucumber", "bdd", "behavior-driven",
24
- "test design", "test design automation", "gherkin", "cucumber",
25
- "specflow", "harmony.ac", "test framework", "model-based test",
26
- "model-based testing", "test model", "test modeling", "test modelling"
27
- ]
28
- }
1
+ {
2
+ "name": "harmonyc",
3
+ "description": "Harmony Code - Test design compiler from high-level model to Gherkin",
4
+ "version": "0.2.0",
5
+ "author": "Bernát Kalló",
6
+ "bin": {
7
+ "harmonyc": "./cli.js"
8
+ },
9
+ "homepage": "https://github.com/harmony-ac/code#readme",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/harmony-ac/code.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/harmony-ac/code/issues"
16
+ },
17
+ "dependencies": {
18
+ "fast-glob": "^3.3.2",
19
+ "typescript-parsec": "0.3.4"
20
+ },
21
+ "license": "MIT",
22
+ "keywords": [
23
+ "unit test",
24
+ "unit testing",
25
+ "cucumber",
26
+ "bdd",
27
+ "behavior-driven",
28
+ "test design",
29
+ "test design automation",
30
+ "gherkin",
31
+ "cucumber",
32
+ "specflow",
33
+ "harmony.ac",
34
+ "test framework",
35
+ "model-based test",
36
+ "model-based testing",
37
+ "test model",
38
+ "test modeling",
39
+ "test modelling"
40
+ ]
41
+ }
package/util/xmur3.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.xmur3 = void 0;
4
- // https://stackoverflow.com/a/47593316
4
+ // https://stackoverflow.com/revisions/47593316/25 by bryc (github.com/bryc)
5
5
  function xmur3(str) {
6
6
  let h = 1779033703 ^ str.length;
7
7
  for (let i = 0; i < str.length; i++)