Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to translations to codeceptjs #189

Merged
merged 7 commits into from Aug 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions lib/actor.js
Expand Up @@ -20,9 +20,13 @@ module.exports = function (obj) {
.filter((method) => {
return method !== 'constructor' && method[0] !== '_';})
.forEach((action) => {
obj[action] = function () {
let actionAlias = container.getTranslations() ? container.getTranslations().actionAliasFor(action) : action;
obj[actionAlias] = function () {
let args = arguments;
recorder.addStep(new Step(helper, action), args);
let step = new Step(helper, action);
step.name = actionAlias;
step.setI(container.getTranslations().I);
recorder.addStep(step, args);
return recorder.promise();
};
});
Expand Down
22 changes: 14 additions & 8 deletions lib/command/definitions.js
Expand Up @@ -10,17 +10,17 @@ let output = require('../output');
let fs = require('fs');
let path = require('path');
let template = `
type ICodeceptCallback = (i: CodeceptJS.I) => void;
type ICodeceptCallback = (i: CodeceptJS.{{I}}) => void;

declare const actor: () => CodeceptJS.I;
declare const actor: () => CodeceptJS.{{I}};
declare const Feature: (string: string) => void;
declare const Scenario: (string: string, callback: ICodeceptCallback) => void;
declare const Before: (callback: ICodeceptCallback) => void;
declare const After: (callback: ICodeceptCallback) => void;
declare const within: (selector: string, callback: Function) => void;

declare namespace CodeceptJS {
export interface I {
export interface {{I}} {
{{methods}}
}
}
Expand All @@ -39,16 +39,20 @@ module.exports = function (genPath) {
codecept.init(testsPath);
let helpers = container.helpers();
let suppportI = container.support('I');
let translations = container.getTranslations();
let methods = [];
let actions = [];
for (let name in helpers) {
let helper = helpers[name];
methodsOfObject(helper).forEach((action) => {
let params = getParamNames(helper[action]);
if (params) params = params.join(', ');
if (!params) params = '';
methods.push(` ${(action)}: (${params}) => any; \n`);
actions[action] = 1
let actionAlias = container.getTranslations() ? container.getTranslations().actionAliasFor(action) : action;
if (!actions[actionAlias]) {
let params = getParamNames(helper[action]);
if (params) params = params.join(', ');
if (!params) params = '';
methods.push(` ${(actionAlias)}: (${params}) => any; \n`);
actions[actionAlias] = 1
}
});
}
for (let name in suppportI) {
Expand All @@ -62,6 +66,8 @@ module.exports = function (genPath) {
methods.push(` ${(name)}: (${params}) => any; \n`);
}
let definitionsTemplate = template.replace('{{methods}}', methods.join(''));
definitionsTemplate = definitionsTemplate.replace(/\{\{I\}\}/g, container.getTranslations().I);

fs.writeFileSync(path.join(testsPath, 'steps.d.ts'), definitionsTemplate);
output.print('TypeScript Definitions provide autocompletion in Visual Studio Code and other IDEs');
output.print('Definitions were generated in steps.d.ts');
Expand Down
39 changes: 39 additions & 0 deletions lib/container.js
@@ -1,6 +1,7 @@
'use strict';
let path = require('path');
let colors = require('colors');
let fileExists = require('./utils').fileExists;

function createHelpers(config) {
let helpers = {};
Expand Down Expand Up @@ -59,18 +60,50 @@ function createSupportObjects(config) {
}
if (!objects.I) {
objects.I = require('./actor')();

if (translations.I != 'I') {
objects[translations.I] = objects.I;
}
}

return objects;
}

function loadTranslations(config) {
var translationsObj = {
I: 'I',
actions: {}
};
if (config.translation) {
// check if it is a known translation
if (require('./translations')[config.translation]) {
translationsObj = require('./translations')[config.translation];
} else if (fileExists(path.join(global.codecept_dir, config.translation))) {
// get from a provided file instead
translationsObj = require(path.join(global.codecept_dir, config.translation));
}
}


translationsObj.actionAliasFor = (actualActionName) => {
if (translationsObj.actions && translationsObj.actions && translationsObj.actions[actualActionName]){
return translationsObj.actions[actualActionName];
} else {
return actualActionName;
}
};
return translationsObj;
}

let helpers = {};
let support = {};
let translations = {};

module.exports = {

create: (config) => {
helpers = createHelpers(config.helpers || {});
translations = loadTranslations(config);
support = createSupportObjects(config.include || {});
},

Expand All @@ -85,12 +118,18 @@ module.exports = {
if (!name) {
return helpers;
}

return helpers[name];
},

getTranslations: () => {
return translations;
},

clear: (newHelpers, newSupport) => {
helpers = newHelpers || {};
support = newSupport || {};
translations = loadTranslations({});
}

};
12 changes: 9 additions & 3 deletions lib/step.js
Expand Up @@ -9,18 +9,24 @@ let event = require('./event');
class Step {

constructor(helper, name) {
this.I = 'I';
this.helper = helper;
this.name = name;
this.helperMethod = name;
this.status = 'pending';
this.prefix = this.suffix = '';
}

setI(I) {
this.I = I;
}

run() {
this.args = Array.prototype.slice.call(arguments);
event.emit(event.step.before, this);
let result;
try {
result = this.helper[this.name].apply(this.helper, this.args);
result = this.helper[this.helperMethod].apply(this.helper, this.args);
this.status = 'success';
} catch (err) {
this.status = 'failed';
Expand Down Expand Up @@ -57,11 +63,11 @@ class Step {
}

toString() {
return `${this.prefix}I ${this.humanize()} ${this.humanizeArgs()}${this.suffix}`;
return `${this.prefix}${this.I} ${this.humanize()} ${this.humanizeArgs()}${this.suffix}`;
}

toCode() {
return `${this.prefix}I.${this.name}(${this.humanizeArgs()})${this.suffix}`;
return `${this.prefix}${this.I}.${this.name}(${this.humanizeArgs()})${this.suffix}`;
}

}
Expand Down
1 change: 1 addition & 0 deletions lib/translations/index.js
@@ -0,0 +1 @@
exports['pt-BR'] = require('./pt-BR');
56 changes: 56 additions & 0 deletions lib/translations/pt-BR.js
@@ -0,0 +1,56 @@


module.exports = {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The explicit call to module.exports is really necessary? I think that the translation file needs be a plain .json file instead a .js file

Copy link
Contributor

@DavertMik DavertMik Aug 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable to me to have it as .json but I don't see if it is necessary

I: 'Eu',
actions: {
'amOutsideAngularApp': 'naoEstouEmAplicacaoAngular',
'amInsideAngularApp': 'estouNaAplicacaoAngular',
'waitForElement': 'aguardoPeloElemento',
'waitForClickable': 'aguardoPorClicavel',
'waitForVisible': 'aguardoPorVisivel',
'waitForText': 'aguardoPorTexto',
'moveTo': 'movoPara',
'refresh': 'atualizoAPagina',
'haveModule': 'temModulo',
'resetModule': 'resetoModulo',
'amOnPage': 'estouNaPagina',
'click': 'clico',
'doubleClick': 'clicoDuplamente',
'see': 'vejo',
'dontSee': 'naoVejo',
'selectOption': 'selecionoAOpcao',
'fillField': 'preenchoOCampo',
'pressKey': 'pressioneATecla',
'attachFile': 'anexaOArquivo',
'seeInField': 'vejoNoCampo',
'dontSeeInField': 'naoVejoNoCampo',
'appendField': 'adicionaCampo',
'checkOption': 'marcoOpcao',
'seeCheckboxIsChecked': 'vejoCheckboxMarcado',
'dontSeeCheckboxIsChecked': 'naoVejoCheckboxMarcado',
'grabTextFrom': 'pegoTextoDe',
'grabValueFrom': 'pegoValorDe',
'grabAttributeFrom': 'pegoAtributoDe',
'seeInTitle': 'VejoNoTitulo',
'dontSeeInTitle': 'naoVejoNoTitulo',
'grabTitle': 'pegoOTitulo',
'seeElement': 'vejoElemento',
'dontSeeElement': 'naoVejoElemento',
'seeInSource': 'vejoNoCodigo',
'dontSeeInSource': 'naoVejoNoCodigo',
'executeScript': 'executoScript',
'executeAsyncScript': 'executoScriptAssincrono',
'seeInCurrentUrl': 'vejoNaUrl',
'dontSeeInCurrentUrl': 'naoVejoNaUrl',
'seeCurrentUrlEquals': 'vejoUrlIgualA',
'dontSeeCurrentUrlEquals': 'naoVejoUrlIgualA',
'saveScreenshot': 'salvoCapturaDeTela',
'setCookie': 'definoCookie',
'clearCookie': 'limpoCookies',
'seeCookie': 'vejoCookie',
'dontSeeCookie': 'naoVejoCookie',
'grabCookie': 'pegoCookie',
'resizeWindow': 'redimensionaJanela',
'wait': 'aguardo'
}
}