Phrases
Phrases, or 'Human Readable Phrases' are a pattern of obscuring implementation details when writing gherkin, by creating phrases that can be transformed into index keys of some object.
Imagine are performing an API test and we have 2 relevant steps:
When I create the user- Makes a HTTP call to our APIs POST /user endpoint with the DTO { name: "John", email: "john@bobmail.com" }
 - Stores the response in the World object under the key 
createUserResponse 
Then 'createUserResponse' result is 'OK'- Asserts that the response stored in the World object under the key 
createUserResponsehas a status code of 200 - Generic step that can be reused across any API test
 - We want to use a more abstracted key, 
'Create User'instead of implementation detail'createUserResponse' 
- Asserts that the response stored in the World object under the key 
 
Using Phrases
- Exposed Details
 - Human Friendly Phrase
 
Scenario: Creating a user
  Given I have a user with the name "John"
  And the users email is "john@bobmail.com"
  When I create the user
  Then 'createUserResponse' result is 'OK'
import { Given, When, Then } from "@autometa/runner";
import { StatusCodes } from "@autometa/status-codes";
Given("I have a user with the name {string}", ({ world }, name) => {
  world.createUserDto = { name };
});
Given("the users email is {string}", ({ world }, email) => {
  world.createUserDto.email = email;
});
When("I create the user", async ({ world, http }) => {
  world.createUserResponse = await http.post("/user", world.createUserDto);
});
Then(
  "{string} result is {string}",
  (property, status, { world }, key, value: keyof StatusCodes) => {
    // assert status to equal { status: 200, statusText: "OK" }
    expect(world[key].status).toEqual(StatusCodes[value]);
  }
);
Scenario: Creating a user
  Given I have a user with the name "John"
  And the users email is "john@bobmail.com"
  When I create the user
  Then 'Create User' result is 'OK'
This removes the code-style camelCased variable, but no longer represents a property of the world.
To accomplish this, we can access the World.fromPhrase method, which will process the gherkin
string with some rules we can define, such as making it camelCase or snake_case, or adding a
prefix or suffix
import { Given, When, Then, sfx, camelCase } from "@autometa/runner";
import { StatusCodes } from "@autometa/status-codes";
Given("I have a user with the name {string}", ({ world }, name) => {
  world.createUserDto = { name };
});
Given("the users email is {string}", ({ world }, email) => {
  world.createUserDto.email = email;
});
When("I create the user", async ({ world, http }) => {
  world.createUserResponse = await http.post("/user", world.createUserDto);
});
Then(
  "{string} result is {string}",
  (property, status, { world }, key, value: keyof StatusCodes) => {
    // 'Create User' -> 'Create User Response' -> 'createUserResponse'
    const key = world.fromPhrase(property, sfx`Response`, camel);
    expect(world[key].status).toEqual(StatusCodes[value]);
  }
);
import { AutometaWorld } from "@autometa/runner";
import { HTTPResponse } from "http-library";
export class World extends AutometaWorld {
  declare createUserDto: CreateUserDto;
  declare createUserResponse: HTTPResponse;
}
Transformers
Phrases are controlled by transformer or mutation actions which are appended
to the phrase. They are applied in the order they are defined. Some, like the case-mutations (camel, upper) will
override previous.
camel- converts the phrase to camelCasesnake- converts the phrase to snake_casekebab- converts the phrase to kebab-casepascal- converts the phrase to PascalCasesfx- adds a suffix to the phrase with a spacepfx- adds a prefix to the phrase with a spacetrim- trims the phrase, removing all white leading and trailing spacelower- converts the phrase to lower caseupper- converts the phrase to upper case
It's also possible to use phrases generically, in your steps or in other parts of your supporting code
import { camel, sfx, From } from "@autometa/runner";
const dummyObject = {
  statusCode: 200
  statusText: 'OK'
};
const status = From(dummyObject).byPhrase("status", sfx`text`, camel) as string;
You can also attach a phrase parser to classes with a decorator:
import { camel, sfx, From, IFromPhrase PhraseParser } from "@autometa/runner";
@PhraseParser
class DummyObject {
  statusCode: number;
  statusText: string;
  declare fromPhrase: IFromPhrase
}
A phrase parser will be injected into instances of the class and can be used directly:
const dummyObject = new DummyObject();
const status = dummyObject.fromPhrase("status", sfx`text`, camel) as string;
Only one case mutation can be succesfully applied to a phrase, however some custom
output formats should be achievable.
For example the format dbCollection__Users could be achieved with
From(foo).byPhrase("Db Collection", camel, sfx`__Users`, trim);
Which camel cases the phrase, adds a suffix of __Users and trims white space between them.