Skip to content

Commit b652bd5

Browse files
authored
fix: gherkin supports i18n (#3934)
1 parent 01b94fd commit b652bd5

File tree

15 files changed

+147
-1
lines changed

15 files changed

+147
-1
lines changed

lib/interfaces/gherkin.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ parser.stopAtFirstError = false;
1818

1919
module.exports = (text, file) => {
2020
const ast = parser.parse(text);
21+
let currentLanguage;
22+
23+
if (ast.feature) {
24+
currentLanguage = getTranslation(ast.feature.language);
25+
}
2126

2227
if (!ast.feature) {
2328
throw new Error(`No 'Features' available in Gherkin '${file}' provided!`);
@@ -96,7 +101,7 @@ module.exports = (text, file) => {
96101
suite.beforeEach('Before', scenario.injected(async () => runSteps(child.background.steps), suite, 'before'));
97102
continue;
98103
}
99-
if (child.scenario && child.scenario.keyword === 'Scenario Outline') {
104+
if (child.scenario && (currentLanguage ? child.scenario.keyword === currentLanguage.contexts.ScenarioOutline : child.scenario.keyword === 'Scenario Outline')) {
100105
for (const examples of child.scenario.examples) {
101106
const fields = examples.tableHeader.cells.map(c => c.value);
102107
for (const example of examples.tableBody) {
@@ -162,3 +167,17 @@ function addExampleInTable(exampleSteps, placeholders) {
162167
}
163168
return steps;
164169
}
170+
171+
function getTranslation(language) {
172+
const translations = Object.keys(require('../../translations'));
173+
174+
for (const availableTranslation of translations) {
175+
if (!language) {
176+
break;
177+
}
178+
179+
if (availableTranslation.includes(language)) {
180+
return require('../../translations')[availableTranslation];
181+
}
182+
}
183+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const I = actor();
2+
3+
Given('ich habe ein Produkt mit einem Preis von {int}$ in meinem Warenkorb', (price) => {
4+
I.addItem(parseInt(price, 10));
5+
});
6+
7+
Given('der Rabatt für Bestellungen über $\{int} beträgt {int} %', (maxPrice, discount) => { // eslint-disable-line
8+
I.haveDiscountForPrice(maxPrice, discount);
9+
});
10+
11+
When('ich zur Kasse gehe', () => {
12+
I.checkout();
13+
});
14+
15+
Then('sollte ich den Gesamtpreis von "{float}" $ sehen', (price) => {
16+
I.seeSum(price);
17+
});
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
exports.config = {
2+
tests: './*_no_test.js',
3+
timeout: 10000,
4+
output: '../output',
5+
helpers: {
6+
BDD: {
7+
require: '../support/bdd_helper.js',
8+
},
9+
},
10+
gherkin: {
11+
features: './features/examples.de.feature',
12+
steps: [
13+
'./features/step_definitions/my_steps.de.js',
14+
],
15+
},
16+
include: {},
17+
bootstrap: false,
18+
mocha: {},
19+
name: 'sandbox',
20+
translation: 'de-DE',
21+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#language: de
2+
Funktionalität: Checkout-Prozess
3+
Um Produkte zu kaufen
4+
Als Kunde
5+
Möchte ich in der Lage sein, mehrere Produkte zu kaufen
6+
7+
@i18n
8+
Szenariogrundriss: Bestellrabatt
9+
Angenommen ich habe ein Produkt mit einem Preis von <price>$ in meinem Warenkorb
10+
Und der Rabatt für Bestellungen über $20 beträgt 10 %
11+
Wenn ich zur Kasse gehe
12+
Dann sollte ich den Gesamtpreis von "<total>" $ sehen
13+
14+
Beispiele:
15+
| price | total |
16+
| 10 | 10.0 |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const I = actor();
2+
3+
Given('ich habe ein Produkt mit einem Preis von {int}$ in meinem Warenkorb', (price) => {
4+
I.addItem(parseInt(price, 10));
5+
});
6+
7+
Given('der Rabatt für Bestellungen über $\{int} beträgt {int} %', (maxPrice, discount) => { // eslint-disable-line
8+
I.haveDiscountForPrice(maxPrice, discount);
9+
});
10+
11+
When('ich zur Kasse gehe', () => {
12+
I.checkout();
13+
});
14+
15+
Then('sollte ich den Gesamtpreis von "{float}" $ sehen', (price) => {
16+
I.seeSum(price);
17+
});

test/runner/bdd_test.js

+27
Original file line numberDiff line numberDiff line change
@@ -315,4 +315,31 @@ When(/^I define a step with a \\( paren and a "(.*?)" string$/, () => {
315315
done();
316316
});
317317
});
318+
319+
describe('i18n', () => {
320+
const codecept_dir = path.join(__dirname, '/../data/sandbox/i18n');
321+
const config_run_config = config => `${codecept_run} --config ${codecept_dir}/${config}`;
322+
323+
before(() => {
324+
process.chdir(codecept_dir);
325+
});
326+
it('should run feature files in DE', (done) => {
327+
exec(config_run_config('codecept.bdd.de.js') + ' --steps --grep "@i18n"', (err, stdout, stderr) => { //eslint-disable-line
328+
stdout.should.include('On Angenommen: ich habe ein produkt mit einem preis von 10$ in meinem warenkorb');
329+
stdout.should.include('On Und: der rabatt für bestellungen über $20 beträgt 10 %');
330+
stdout.should.include('On Wenn: ich zur kasse gehe');
331+
stdout.should.include('On Dann: sollte ich den gesamtpreis von "10.0" $ sehen');
332+
stdout.should.include('On Angenommen: ich habe ein produkt mit einem preis von 10$ in meinem warenkorb');
333+
stdout.should.include('Ich add item 10');
334+
stdout.should.include('On Und: der rabatt für bestellungen über $20 beträgt 10 %');
335+
stdout.should.include('Ich have discount for price 20, 10');
336+
stdout.should.include('On Wenn: ich zur kasse gehe');
337+
stdout.should.include('Ich checkout');
338+
stdout.should.include('On Dann: sollte ich den gesamtpreis von "10.0" $ sehen');
339+
stdout.should.include('Ich see sum 10');
340+
assert(!err);
341+
done();
342+
});
343+
});
344+
});
318345
});

translations/de-DE.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
module.exports = {
22
I: 'Ich',
3+
contexts: {
4+
Feature: 'Funktionalität',
5+
Scenario: 'Szenario',
6+
ScenarioOutline: 'Szenariogrundriss',
7+
},
38
actions: {
49
amOutsideAngularApp: 'befinde_mich_außerhalb_der_angular_app',
510
amInsideAngularApp: 'bedinde_mich_innerhalb_der_angular_app',

translations/fr-FR.js

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module.exports = {
33
contexts: {
44
Feature: 'Fonctionnalité',
55
Scenario: 'Scénario',
6+
ScenarioOutline: 'Plan du scénario',
67
Before: 'Avant',
78
After: 'Après',
89
BeforeSuite: 'AvantLaSuite',

translations/it-IT.js

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module.exports = {
33
contexts: {
44
Feature: 'Caratteristica',
55
Scenario: 'lo_scenario',
6+
ScenarioOutline: 'Schema dello scenario',
67
Before: 'Prima',
78
After: 'Dopo',
89
BeforeSuite: 'Prima_della_suite',

translations/ja-JP.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
module.exports = {
22
I: '私は',
3+
contexts: {
4+
Feature: 'フィーチャ',
5+
Scenario: 'シナリオ',
6+
ScenarioOutline: 'シナリオアウトライン',
7+
},
38
actions: {
49
amOutsideAngularApp: 'Angularの外に出る',
510
amInsideAngularApp: 'Angularの中に入る',

translations/pl-PL.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
module.exports = {
22
I: 'Ja',
3+
contexts: {
4+
Feature: 'Funkcja',
5+
Scenario: 'Scenariusz',
6+
ScenarioOutline: 'Szablon scenariusza',
7+
},
38
actions: {
49
amOutsideAngularApp: 'jestem_poza_aplikacją_angular',
510
amInsideAngularApp: 'jestem_w_aplikacji_angular',

translations/pt-BR.js

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module.exports = {
33
contexts: {
44
Feature: 'Funcionalidade',
55
Scenario: 'Cenário',
6+
ScenarioOutline: 'Esquema do Cenário',
67
Before: 'Antes',
78
After: 'Depois',
89
BeforeSuite: 'AntesDaSuite',

translations/ru-RU.js

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module.exports = {
33
contexts: {
44
Feature: 'Цель',
55
Scenario: 'Сценарий',
6+
ScenarioOutline: 'Структура сценария',
67
Before: 'Начало',
78
After: 'Конец',
89
BeforeSuite: 'Перед_всем',

translations/zh-CN.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
module.exports = {
22
I: '我',
3+
contexts: {
4+
Feature: '功能',
5+
Scenario: '场景',
6+
ScenarioOutline: '场景大纲',
7+
},
38
actions: {
49
amOutsideAngularApp: '在Angular应用外',
510
amInsideAngularApp: '在Angular应用内',

translations/zh-TW.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
module.exports = {
22
I: '我',
3+
contexts: {
4+
Feature: '功能',
5+
Scenario: '場景',
6+
ScenarioOutline: '場景大綱',
7+
},
38
actions: {
49
amOutsideAngularApp: '在Angular應用外',
510
amInsideAngularApp: '在Angular應用內',

0 commit comments

Comments
 (0)