harmonyc 0.6.0-5 → 0.6.0-7
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/compile.js +4 -4
- package/filenames/filenames.js +3 -2
- package/js_api/js_api.js +9 -9
- package/languages/JavaScript.js +43 -13
- package/outFile.js +5 -2
- package/package.json +1 -1
- package/run.js +8 -6
package/compile.js
CHANGED
|
@@ -4,11 +4,11 @@ import { parse } from './syntax.js';
|
|
|
4
4
|
import { stepsFileName, testFileName } from './filenames/filenames.js';
|
|
5
5
|
export function compileFeature(fileName, src) {
|
|
6
6
|
const feature = parse({ fileName, src });
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const testFn = testFileName(fileName);
|
|
8
|
+
const testFile = new OutFile(testFn);
|
|
9
9
|
const stepsFn = stepsFileName(fileName);
|
|
10
10
|
const stepsFile = new OutFile(stepsFn);
|
|
11
|
-
const cg = new NodeTest(
|
|
11
|
+
const cg = new NodeTest(testFile, stepsFile);
|
|
12
12
|
feature.toCode(cg);
|
|
13
|
-
return { outFile, stepsFile };
|
|
13
|
+
return { outFile: testFile, stepsFile };
|
|
14
14
|
}
|
package/filenames/filenames.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import glob from 'fast-glob';
|
|
2
|
-
const { globSync } = glob;
|
|
2
|
+
const { globSync, convertPathToPattern } = glob;
|
|
3
3
|
export function base(fn) {
|
|
4
4
|
return fn.replace(/\.harmony\.md$/i, '');
|
|
5
5
|
}
|
|
@@ -7,7 +7,8 @@ export function testFileName(fn) {
|
|
|
7
7
|
return base(fn) + '.test.mjs';
|
|
8
8
|
}
|
|
9
9
|
export function stepsFileName(fn) {
|
|
10
|
-
const
|
|
10
|
+
const pattern = convertPathToPattern(base(fn) + '.steps.*');
|
|
11
|
+
const existing = globSync(pattern);
|
|
11
12
|
if (existing.length) {
|
|
12
13
|
return existing.sort()[0];
|
|
13
14
|
}
|
package/js_api/js_api.js
CHANGED
|
@@ -11,7 +11,7 @@ class Definition {
|
|
|
11
11
|
this.fn = fn;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
const
|
|
14
|
+
const featureDefs = new Map();
|
|
15
15
|
class FeatureContext {
|
|
16
16
|
constructor() {
|
|
17
17
|
_FeatureContext_actions.set(this, []);
|
|
@@ -65,17 +65,17 @@ class FeatureContext {
|
|
|
65
65
|
}
|
|
66
66
|
_FeatureContext_actions = new WeakMap(), _FeatureContext_responses = new WeakMap(), _FeatureContext_parameterTypeRegistry = new WeakMap();
|
|
67
67
|
export function Feature(s, fn) {
|
|
68
|
-
let ctx;
|
|
69
68
|
if (!fn) {
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
// instantiate the feature
|
|
70
|
+
const fn = featureDefs.get(s);
|
|
71
|
+
if (!fn)
|
|
72
72
|
throw new Error(`Feature not found: ${s}`);
|
|
73
|
+
const ctx = new FeatureContext();
|
|
74
|
+
fn(ctx);
|
|
75
|
+
return ctx;
|
|
73
76
|
}
|
|
74
77
|
else {
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
features.set(s, ctx);
|
|
78
|
+
// (re)define the feature
|
|
79
|
+
featureDefs.set(s, fn);
|
|
78
80
|
}
|
|
79
|
-
fn === null || fn === void 0 ? void 0 : fn(ctx);
|
|
80
|
-
return ctx;
|
|
81
81
|
}
|
package/languages/JavaScript.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { basename } from 'path';
|
|
2
2
|
export class NodeTest {
|
|
3
|
-
constructor(
|
|
4
|
-
this.
|
|
3
|
+
constructor(tf, sf) {
|
|
4
|
+
this.tf = tf;
|
|
5
5
|
this.sf = sf;
|
|
6
6
|
this.framework = 'vitest';
|
|
7
7
|
this.phrases = [];
|
|
@@ -10,21 +10,21 @@ export class NodeTest {
|
|
|
10
10
|
const stepsModule = './' + basename(this.sf.name.replace(/.(js|ts)$/, ''));
|
|
11
11
|
this.phrases = [];
|
|
12
12
|
if (this.framework === 'vitest') {
|
|
13
|
-
this.
|
|
14
|
-
this.
|
|
15
|
-
this.
|
|
13
|
+
this.tf.print(`import { test, expect } from 'vitest';`);
|
|
14
|
+
this.tf.print(`import { Feature } from 'harmonyc/test';`);
|
|
15
|
+
this.tf.print(`import ${str(stepsModule)};`);
|
|
16
16
|
}
|
|
17
17
|
for (const test of feature.tests) {
|
|
18
18
|
test.toCode(this);
|
|
19
19
|
}
|
|
20
20
|
this.sf.print(`import { Feature } from 'harmonyc/test';`);
|
|
21
21
|
this.sf.print('');
|
|
22
|
-
this.sf.print(`Feature(${
|
|
22
|
+
this.sf.print(`Feature(${str(feature.name)}, ({ Action, Response }) => {`);
|
|
23
23
|
this.sf.indent(() => {
|
|
24
24
|
for (const phrase of this.phrases) {
|
|
25
|
-
this.sf.print(`${capitalize(phrase.kind)}(${
|
|
25
|
+
this.sf.print(`${capitalize(phrase.kind)}(${str(phrase.text)}, () => {`);
|
|
26
26
|
this.sf.indent(() => {
|
|
27
|
-
this.sf.print(`throw new Error(${
|
|
27
|
+
this.sf.print(`throw new Error(${str(`Pending: ${phrase.text}`)})`);
|
|
28
28
|
});
|
|
29
29
|
this.sf.print('})');
|
|
30
30
|
}
|
|
@@ -32,22 +32,52 @@ export class NodeTest {
|
|
|
32
32
|
this.sf.print('})');
|
|
33
33
|
}
|
|
34
34
|
test(t) {
|
|
35
|
-
this.
|
|
36
|
-
this.
|
|
35
|
+
this.featureVars = new Map();
|
|
36
|
+
this.tf.print(`test('${t.name}', async (context) => {`);
|
|
37
|
+
this.tf.indent(() => {
|
|
37
38
|
for (const step of t.steps) {
|
|
38
39
|
step.toCode(this);
|
|
39
40
|
}
|
|
40
41
|
});
|
|
41
|
-
this.
|
|
42
|
-
this.
|
|
42
|
+
this.tf.print('})');
|
|
43
|
+
this.tf.print('');
|
|
43
44
|
}
|
|
44
45
|
phrase(p) {
|
|
45
46
|
if (!this.phrases.some((x) => x.text === p.text))
|
|
46
47
|
this.phrases.push(p);
|
|
47
48
|
const feature = p.feature.name;
|
|
48
|
-
this.
|
|
49
|
+
let f = this.featureVars.get(feature);
|
|
50
|
+
if (!f) {
|
|
51
|
+
f = toId(feature, this.featureVars);
|
|
52
|
+
this.tf.print(`const ${f} = Feature(${str(feature)})`);
|
|
53
|
+
}
|
|
54
|
+
this.tf.print(`await ${f}.${capitalize(p.kind)}(${str(p.text)})`);
|
|
49
55
|
}
|
|
50
56
|
}
|
|
57
|
+
function str(s) {
|
|
58
|
+
let r = JSON.stringify(s);
|
|
59
|
+
return r;
|
|
60
|
+
}
|
|
51
61
|
function capitalize(s) {
|
|
52
62
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
53
63
|
}
|
|
64
|
+
function toId(s, previous) {
|
|
65
|
+
if (previous.has(s))
|
|
66
|
+
return previous.get(s);
|
|
67
|
+
let base = pascalCase(s);
|
|
68
|
+
let id = base;
|
|
69
|
+
if ([...previous.values()].includes(id)) {
|
|
70
|
+
let i = 1;
|
|
71
|
+
while ([...previous.values()].includes(id + i))
|
|
72
|
+
i++;
|
|
73
|
+
id = base + i;
|
|
74
|
+
}
|
|
75
|
+
previous.set(s, id);
|
|
76
|
+
return id;
|
|
77
|
+
}
|
|
78
|
+
function pascalCase(s) {
|
|
79
|
+
return s
|
|
80
|
+
.split(/[^a-zA-Z0-9]/)
|
|
81
|
+
.map(capitalize)
|
|
82
|
+
.join('');
|
|
83
|
+
}
|
package/outFile.js
CHANGED
|
@@ -40,7 +40,10 @@ export class OutFile {
|
|
|
40
40
|
return this;
|
|
41
41
|
}
|
|
42
42
|
get value() {
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
let res = this.lines.join('\n');
|
|
44
|
+
if (this.currentLoc) {
|
|
45
|
+
res += `\n\n//# sourceMappingURL=data:application/json,${encodeURIComponent(this.sm.toString())}`;
|
|
46
|
+
}
|
|
47
|
+
return res;
|
|
45
48
|
}
|
|
46
49
|
}
|
package/package.json
CHANGED
package/run.js
CHANGED
|
@@ -9,16 +9,18 @@ function args(patterns) {
|
|
|
9
9
|
return patterns.map((s) => JSON.stringify(s)).join(' ');
|
|
10
10
|
}
|
|
11
11
|
export function run(patterns) {
|
|
12
|
-
var _a, _b;
|
|
12
|
+
var _a, _b, _c;
|
|
13
13
|
const cmd = runCommand(patterns);
|
|
14
14
|
const p = exec(cmd, { cwd: process.cwd() });
|
|
15
|
-
(_a = p.
|
|
16
|
-
(_b = p.
|
|
15
|
+
(_a = p.stdin) === null || _a === void 0 ? void 0 : _a.pipe(process.stdin);
|
|
16
|
+
(_b = p.stdout) === null || _b === void 0 ? void 0 : _b.pipe(process.stdout);
|
|
17
|
+
(_c = p.stderr) === null || _c === void 0 ? void 0 : _c.pipe(process.stderr);
|
|
17
18
|
}
|
|
18
19
|
export function runWatch(patterns) {
|
|
19
|
-
var _a, _b;
|
|
20
|
+
var _a, _b, _c;
|
|
20
21
|
const cmd = runWatchCommand(patterns);
|
|
21
22
|
const p = exec(cmd, { cwd: process.cwd() });
|
|
22
|
-
(_a = p.
|
|
23
|
-
(_b = p.
|
|
23
|
+
(_a = p.stdin) === null || _a === void 0 ? void 0 : _a.pipe(process.stdin);
|
|
24
|
+
(_b = p.stdout) === null || _b === void 0 ? void 0 : _b.pipe(process.stdout);
|
|
25
|
+
(_c = p.stderr) === null || _c === void 0 ? void 0 : _c.pipe(process.stderr);
|
|
24
26
|
}
|