diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index 7def053..2cb5ad7 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -7,18 +7,15 @@ on:
branches: [ "main" ]
jobs:
-
build:
-
strategy:
matrix:
- #configuration: [Debug, Release]
configuration: [Release]
runs-on: ubuntu-latest
env:
- Version: 1.2.${{ github.run_number }}
+ Version: 1.3.${{ github.run_number }}
Solution_Path: ./src/GherXunit.sln
Project_Path: ./src/lib/GherXunit/GherXunit.csproj
Package_Path: ./src/lib/GherXunit/**/*.
@@ -48,5 +45,4 @@ jobs:
if: github.ref == 'refs/heads/main'
run: |
dotnet pack ${{env.Project_Path}} --no-restore --configuration ${{ matrix.configuration }} -p:PackageVersion=${{ env.Version }}
- dotnet nuget push ${{env.Package_Path}}${{ env.Version }}.nupkg --api-key ${{ secrets.NUGET_KEY }} --source ${{ env.NUGET_INDEX }}
-
\ No newline at end of file
+ dotnet nuget push ${{env.Package_Path}}${{ env.Version }}.nupkg --api-key ${{ secrets.NUGET_KEY }} --source ${{ env.NUGET_INDEX }}
\ No newline at end of file
diff --git a/README.md b/README.md
index 6ca7500..25f5b46 100644
--- a/README.md
+++ b/README.md
@@ -84,17 +84,82 @@ The result of running the test scenarios defined in the `SubscriptionTest` class
```gherkindotnet
TEST RESULT: 🟢 SUCCESS
⤷ FEATURE Subscribers see different articles based on their subscription level
- ⤷ SCENARIO Free subscribers see only the free articles
- | GIVEN ↘ Free Frieda has a free subscription
- | WHEN ↘ Free Frieda logs in with her valid credentials
- | THEN ↘ she sees a Free article
+ ⤷ SCENARIO Free subscribers see only the free articles
+ | GIVEN ↘ Free Frieda has a free subscription
+ | WHEN ↘ Free Frieda logs in with her valid credentials
+ | THEN ↘ she sees a Free article
TEST RESULT: 🟢 SUCCESS
⤷ FEATURE Subscribers see different articles based on their subscription level
- ⤷ SCENARIO Subscriber with a paid subscription can access both free and paid articles
- | GIVEN ↘ Paid Patty has a basic-level paid subscription
- | WHEN ↘ Paid Patty logs in with her valid credentials
- | THEN ↘ she sees a Free article and a Paid article
+ ⤷ SCENARIO Subscriber with a paid subscription can access both free and paid articles
+ | GIVEN ↘ Paid Patty has a basic-level paid subscription
+ | WHEN ↘ Paid Patty logs in with her valid credentials
+ | THEN ↘ she sees a Free article and a Paid article
+```
+
+### ✏️ Customizing the lexical elements of Gherkin
+
+The **GherXunit** allows you to customize the lexical elements of Gherkin, such as `Given`, `When`, `Then`, `And`, `Background`, `Scenario`, and `Feature`.
+You can define your custom emojis or symbols to represent these elements. The following code snippet shows an example of a custom lexer for emojis:
+```csharp
+// Custom lexer for emojis
+public record EmojiGherXunitLexer : IGherXunitLexer
+{
+ public (string Key, string Value)[] Given => [("Given", "\ud83d\ude10")];
+ public (string Key, string Value)[] When => [("When", "\ud83c\udfac")];
+ public (string Key, string Value)[] Then => [("Then", "\ud83d\ude4f")];
+ public (string Key, string Value)[] And => [("And", "\ud83d\ude02")];
+ public string Background => "\ud83d\udca4";
+ public string Scenario => "\ud83e\udd52\ud83d\udcd5";
+ public string Feature => "\ud83d\udcda";
+}
+```
+The Gherkin provides two built-in lexers: `Lexers.PtBr` for Portuguese (🇵🇹🇧🇷) and `Lexers.EnUs` for English (🇺🇸).
+You can also create your custom lexer by implementing the `IGherXunitLexer` interface. To use the custom lexer,
+you need to pass it as a parameter when defining the test scenario.
+
+```csharp
+[Feature("Subscribers see different articles based on their subscription level")]
+public partial class LocalizationTest
+{
+ // Using Portuguese (🇵🇹🇧🇷) lexer
+ [Scenario("Inscrever-se para ver artigos gratuitos")]
+ async Task WhenFriedaLogs() => await this.ExecuteAscync(
+ refer: WhenFriedaLogsSteps,
+ lexer: Lexers.PtBr,
+ steps: """
+ Dado Free Frieda possui uma assinatura gratuita
+ Quando Free Frieda faz login com suas credenciais válidas
+ Então ela vê um artigo gratuito
+ """);
+
+ // Using custom emoji lexer
+ [Scenario("Subscriber with a paid subscription can access both free and paid articles")]
+ void WhenPattyLogs() => this.Execute(
+ refer: WhenPattyLogsSteps,
+ lexer: new EmojiGherXunitLexer(),
+ steps: """
+ Given Paid Patty has a basic-level paid subscription
+ When Paid Patty logs in with her valid credentials
+ Then she sees a Free article and a Paid article
+ """);
+}
+```
+The result of running the test scenarios defined in the `LocalizationTest` class using the custom lexer would be similar to the following output:
+```gherkindotnet
+TEST RESULT: 🟢 SUCCESS
+⤷ FUNCIONALIDADE Subscribers see different articles based on their subscription level
+ ⤷ CENARIO Inscrever-se para ver artigos gratuitos
+ | DADO ↘ Free Frieda possui uma assinatura gratuita
+ | QUANDO ↘ Free Frieda faz login com suas credenciais válidas
+ | ENTÃO ↘ ela vê um artigo gratuito
+
+TEST RESULT: 🟢 SUCCESS
+⤷ 📚 Subscribers see different articles based on their subscription level
+ ⤷ 🥒📕 Subscriber with a paid subscription can access both free and paid articles
+ | 😐 ↘ Paid Patty has a basic-level paid subscription
+ | 🎬 ↘ Paid Patty logs in with her valid credentials
+ | 🙏 ↘ she sees a Free article and a Paid article
```
### 🔎 Is GherXunit for You?
diff --git a/README_PTBR.md b/README_PTBR.md
index 0e2188b..e1f59fd 100644
--- a/README_PTBR.md
+++ b/README_PTBR.md
@@ -83,20 +83,87 @@ public partial class SubscriptionTest(ITestOutputHelper output): IGherXunit
#### 📌 Exemplo de saída destacando os resultados dos testes:
O resultado da execução dos cenários de teste definidos na classe `SubscriptionTest` seria semelhante à saída a seguir:
-```shell
+```gherkindotnet
TEST RESULT: 🟢 SUCCESS
⤷ FEATURE Subscribers see different articles based on their subscription level
- ⤷ SCENARIO Free subscribers see only the free articles
- | GIVEN ↘ Free Frieda has a free subscription
- | WHEN ↘ Free Frieda logs in with her valid credentials
- | THEN ↘ she sees a Free article
+ ⤷ SCENARIO Free subscribers see only the free articles
+ | GIVEN ↘ Free Frieda has a free subscription
+ | WHEN ↘ Free Frieda logs in with her valid credentials
+ | THEN ↘ she sees a Free article
TEST RESULT: 🟢 SUCCESS
⤷ FEATURE Subscribers see different articles based on their subscription level
- ⤷ SCENARIO Subscriber with a paid subscription can access both free and paid articles
- | GIVEN ↘ Paid Patty has a basic-level paid subscription
- | WHEN ↘ Paid Patty logs in with her valid credentials
- | THEN ↘ she sees a Free article and a Paid article
+ ⤷ SCENARIO Subscriber with a paid subscription can access both free and paid articles
+ | GIVEN ↘ Paid Patty has a basic-level paid subscription
+ | WHEN ↘ Paid Patty logs in with her valid credentials
+ | THEN ↘ she sees a Free article and a Paid article
+```
+
+### ✏️ Customizando a Sintaxe Gherkin
+
+O **GherXunit** permite personalizar os elementos lexicais do Gherkin, como `Given`, `When`, `Then`, `And`, `Background`, `Scenario` e `Feature`.
+Você pode definir seus emojis ou símbolos personalizados para representar esses elementos. O trecho de código a seguir mostra um exemplo de um lexer personalizado para emojis:
+
+```csharp
+// Custom lexer for emojis
+public record EmojiGherXunitLexer : IGherXunitLexer
+{
+ public (string Key, string Value)[] Given => [("Given", "\ud83d\ude10")];
+ public (string Key, string Value)[] When => [("When", "\ud83c\udfac")];
+ public (string Key, string Value)[] Then => [("Then", "\ud83d\ude4f")];
+ public (string Key, string Value)[] And => [("And", "\ud83d\ude02")];
+ public string Background => "\ud83d\udca4";
+ public string Scenario => "\ud83e\udd52\ud83d\udcd5";
+ public string Feature => "\ud83d\udcda";
+}
+```
+O **GherXunit** fornece dois lexers embutidos: `Lexers.PtBr` para Português (🇵🇹🇧🇷) e `Lexers.EnUs` para Inglês (🇺🇸).
+Você também pode criar seu lexer personalizado implementando a interface `IGherXunitLexer`. Para usar o lexer personalizado,
+você precisa passá-lo como parâmetro ao definir o cenário de teste.
+
+```csharp
+[Feature("Subscribers see different articles based on their subscription level")]
+public partial class LocalizationTest
+{
+ // Using Portuguese (🇵🇹🇧🇷) lexer
+ [Scenario("Inscrever-se para ver artigos gratuitos")]
+ async Task WhenFriedaLogs() => await this.ExecuteAscync(
+ refer: WhenFriedaLogsSteps,
+ lexer: Lexers.PtBr,
+ steps: """
+ Dado Free Frieda possui uma assinatura gratuita
+ Quando Free Frieda faz login com suas credenciais válidas
+ Então ela vê um artigo gratuito
+ """);
+
+ // Using custom emoji lexer
+ [Scenario("Subscriber with a paid subscription can access both free and paid articles")]
+ void WhenPattyLogs() => this.Execute(
+ refer: WhenPattyLogsSteps,
+ lexer: new EmojiGherXunitLexer(),
+ steps: """
+ Given Paid Patty has a basic-level paid subscription
+ When Paid Patty logs in with her valid credentials
+ Then she sees a Free article and a Paid article
+ """);
+}
+```
+
+O resultado da execução dos cenários de teste definidos na classe `LocalizationTest` usando o lexer personalizado seria semelhante à saída a seguir:
+```gherkindotnet
+TEST RESULT: 🟢 SUCCESS
+⤷ FUNCIONALIDADE Subscribers see different articles based on their subscription level
+ ⤷ CENARIO Inscrever-se para ver artigos gratuitos
+ | DADO ↘ Free Frieda possui uma assinatura gratuita
+ | QUANDO ↘ Free Frieda faz login com suas credenciais válidas
+ | ENTÃO ↘ ela vê um artigo gratuito
+
+TEST RESULT: 🟢 SUCCESS
+⤷ 📚 Subscribers see different articles based on their subscription level
+ ⤷ 🥒📕 Subscriber with a paid subscription can access both free and paid articles
+ | 😐 ↘ Paid Patty has a basic-level paid subscription
+ | 🎬 ↘ Paid Patty logs in with her valid credentials
+ | 🙏 ↘ she sees a Free article and a Paid article
```
### 🔎 O GherXunit é para você?
diff --git a/src/GherXunit.sln b/src/GherXunit.sln
index 7e2d696..9397b42 100644
--- a/src/GherXunit.sln
+++ b/src/GherXunit.sln
@@ -2,12 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{8B016D41-92A4-4ABC-9D36-D9A13D3B0E7D}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{FF816255-012E-4E4D-9C2B-E8AE0CE481A3}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GherXunit", "lib\GherXunit\GherXunit.csproj", "{121FDFEF-6F96-48F9-8DB3-ED4775C5E9F6}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BddSample", "sample\BddSample\BddSample.csproj", "{4A38E3EA-C8A3-4F02-B7D5-BC63C302865B}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "base", "base", "{B014B043-DFB5-4827-8775-D4E5326130F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GherXunit.Core", "base\GherXunit.Core\GherXunit.Core.csproj", "{5477E886-B647-4A5D-A522-2978AF9F748D}"
@@ -19,7 +15,6 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{121FDFEF-6F96-48F9-8DB3-ED4775C5E9F6} = {8B016D41-92A4-4ABC-9D36-D9A13D3B0E7D}
- {4A38E3EA-C8A3-4F02-B7D5-BC63C302865B} = {FF816255-012E-4E4D-9C2B-E8AE0CE481A3}
{5477E886-B647-4A5D-A522-2978AF9F748D} = {B014B043-DFB5-4827-8775-D4E5326130F0}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
@@ -27,10 +22,6 @@ Global
{121FDFEF-6F96-48F9-8DB3-ED4775C5E9F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{121FDFEF-6F96-48F9-8DB3-ED4775C5E9F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{121FDFEF-6F96-48F9-8DB3-ED4775C5E9F6}.Release|Any CPU.Build.0 = Release|Any CPU
- {4A38E3EA-C8A3-4F02-B7D5-BC63C302865B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4A38E3EA-C8A3-4F02-B7D5-BC63C302865B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4A38E3EA-C8A3-4F02-B7D5-BC63C302865B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4A38E3EA-C8A3-4F02-B7D5-BC63C302865B}.Release|Any CPU.Build.0 = Release|Any CPU
{5477E886-B647-4A5D-A522-2978AF9F748D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5477E886-B647-4A5D-A522-2978AF9F748D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5477E886-B647-4A5D-A522-2978AF9F748D}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/src/base/GherXunit.Core/GherXunit.Core.csproj b/src/base/GherXunit.Core/GherXunit.Core.csproj
index 1d2dd89..7c3f420 100644
--- a/src/base/GherXunit.Core/GherXunit.Core.csproj
+++ b/src/base/GherXunit.Core/GherXunit.Core.csproj
@@ -12,6 +12,8 @@
+
+
diff --git a/src/base/GherXunit.Core/Interfaces.cs b/src/base/GherXunit.Core/Interfaces.cs
index 916e7fd..081e8d7 100644
--- a/src/base/GherXunit.Core/Interfaces.cs
+++ b/src/base/GherXunit.Core/Interfaces.cs
@@ -17,4 +17,16 @@ public interface IGherXunit : IGherXunit, IClassFixture where T : class;
public interface IGherXunitOutputProvider
{
public ITestOutputHelper Output { get; }
-}
\ No newline at end of file
+}
+
+//Lexer
+public interface IGherXunitLexer
+{
+ public (string Key, string Value)[] Given { get; }
+ public (string Key, string Value)[] When { get; }
+ public (string Key, string Value)[] Then { get; }
+ public (string Key, string Value)[] And { get; }
+ public string Background { get; }
+ public string Scenario { get; }
+ public string Feature { get; }
+}
diff --git a/src/base/GherXunit.Core/Methods.cs b/src/base/GherXunit.Core/Methods.cs
index c6b4c6b..c3e2cf8 100644
--- a/src/base/GherXunit.Core/Methods.cs
+++ b/src/base/GherXunit.Core/Methods.cs
@@ -7,54 +7,52 @@ namespace GherXunit.Annotations;
public static class GherXunitSteps
{
- // Async methods
- public static async Task BackgroundAsync(this IGherXunitStep scenario, Delegate refer, string steps) => await ExecuteAscync(scenario, refer.Method, steps, true);
- public static async Task ExecuteAscync(this IGherXunitStep scenario, string steps) => await ExecuteAscync(scenario, null, steps, false);
- public static async Task ExecuteAscync(this IGherXunitStep scenario, Delegate refer, string steps) => await ExecuteAscync(scenario, refer.Method, steps);
- public static async Task ExecuteAscync(this IGherXunitStep scenario, Delegate refer, object[] param, string steps) => await ExecuteAscync(scenario, refer.Method, steps, false, param);
- public static async Task NonExecutableAsync(this IGherXunitStep scenario, string? steps = null) => await ExecuteAscync(scenario, null, steps, false);
-
- // Sync methods
- public static void Background(this IGherXunitStep scenario, Delegate refer, string steps) => Execute(scenario, refer.Method, steps, true);
- public static void Execute(this IGherXunitStep scenario, string steps) => Execute(scenario, null, steps, false);
- public static void Execute(this IGherXunitStep scenario, Delegate refer, string steps) => Execute(scenario, refer.Method, steps);
- public static void Execute(this IGherXunitStep scenario, Delegate refer, object[] param, string steps) => Execute(scenario, refer.Method, steps, false, param);
- public static void NonExecutable(this IGherXunitStep feature, string? steps) => Execute(feature, null, steps, false, []);
+ // Background methods
+ public static void Background(this IGherXunitStep scenario, Delegate refer, string steps, IGherXunitLexer? lexer = null) => InternalExecute(scenario, refer.Method, steps, true, lexer);
+ public static async Task BackgroundAsync(this IGherXunitStep scenario, Delegate refer, string steps, IGherXunitLexer? lexer = null) => await InternalExecuteAscync(scenario, refer.Method, steps, true, lexer);
+
+ // Execute methods
+ public static void Execute(this IGherXunitStep scenario, string steps, Delegate? refer = null, object[]? param = null, IGherXunitLexer? lexer = null) => InternalExecute(scenario, refer?.Method, steps, false, lexer, param);
+ public static async Task ExecuteAscync(this IGherXunitStep scenario, string steps, Delegate? refer = null, object[]? param = null, IGherXunitLexer? lexer = null) => await InternalExecuteAscync(scenario, refer?.Method, steps, false, lexer, param);
+
+ // Non Executable
+ public static void NonExecutable(this IGherXunitStep feature, string steps, IGherXunitLexer? lexer = null) => InternalExecute(feature, null, steps, false, lexer);
+ public static async Task NonExecutableAsync(this IGherXunitStep scenario, string steps, IGherXunitLexer? lexer = null) => await InternalExecuteAscync(scenario, null, steps, false, lexer);
// Private methods
- private static void Execute(this IGherXunitStep scenario, MethodInfo? method, string? steps,
- bool isBackground = false, params object?[] param)
+ private static void InternalExecute(this IGherXunitStep scenario, MethodInfo? method, string? steps,
+ bool isBackground = false, IGherXunitLexer? lexer = null, params object[]? param)
{
try
{
method?.Invoke(scenario, param);
- scenario.Write(method?.Name, steps, false, isBackground);
+ scenario.Write(method?.Name, steps, false, isBackground, lexer);
}
catch (Exception)
{
- scenario.Write(method?.Name, steps, true, isBackground);
+ scenario.Write(method?.Name, steps, true, isBackground, lexer);
throw;
}
}
- private static async Task ExecuteAscync(this IGherXunitStep scenario, MethodInfo? method, string? steps,
- bool isBackground = false, params object?[] param)
+ private static async Task InternalExecuteAscync(this IGherXunitStep scenario, MethodInfo? method, string? steps,
+ bool isBackground = false, IGherXunitLexer? lexer = null, params object[]? param)
{
try
{
var task = method is null ? Task.CompletedTask : (Task)method.Invoke(scenario, param)!;
await task;
- scenario.Write(method?.Name, steps, false, isBackground);
+ scenario.Write(method?.Name, steps, false, isBackground, lexer);
}
catch (Exception)
{
- scenario.Write(method?.Name, steps, true, isBackground);
+ scenario.Write(method?.Name, steps, true, isBackground, lexer);
throw;
}
}
- private static void Write(this IGherXunitStep scenario, string? methodName, string? steps, bool isException = false, bool isBackground = false)
+ private static void Write(this IGherXunitStep scenario, string? methodName, string? steps, bool isException = false, bool isBackground = false, IGherXunitLexer? lexer = null)
{
if (steps is null) return;
@@ -65,8 +63,8 @@ private static void Write(this IGherXunitStep scenario, string? methodName, stri
var scenarioText = iTest is null
? $"{(isBackground ? "Background" : "Scenario")} {methodName}\r\n"
: $"{(isBackground ? "Background" : "Scenario")} {iTest.DisplayName}\r\n";
-
- var stepString = new StepStringHandler();
+
+ var stepString = new StringHandler(lexer ?? Lexers.EnUs);
stepString.AppendLiteral($"{statusResult}{featuresText}{scenarioText}{steps}");
output?.WriteLine(".");
diff --git a/src/base/GherXunit.Core/Backgrounds/BackgroundTest.Context.cs b/src/base/GherXunit.Core/Samples/Backgrounds/BackgroundTest.Context.cs
similarity index 100%
rename from src/base/GherXunit.Core/Backgrounds/BackgroundTest.Context.cs
rename to src/base/GherXunit.Core/Samples/Backgrounds/BackgroundTest.Context.cs
diff --git a/src/base/GherXunit.Core/Backgrounds/BackgroundTest.Steps.cs b/src/base/GherXunit.Core/Samples/Backgrounds/BackgroundTest.Steps.cs
similarity index 100%
rename from src/base/GherXunit.Core/Backgrounds/BackgroundTest.Steps.cs
rename to src/base/GherXunit.Core/Samples/Backgrounds/BackgroundTest.Steps.cs
diff --git a/src/base/GherXunit.Core/Backgrounds/BackgroundTest.cs b/src/base/GherXunit.Core/Samples/Backgrounds/BackgroundTest.cs
similarity index 100%
rename from src/base/GherXunit.Core/Backgrounds/BackgroundTest.cs
rename to src/base/GherXunit.Core/Samples/Backgrounds/BackgroundTest.cs
diff --git a/src/base/GherXunit.Core/Features/SubscriptionTest.Steps.cs b/src/base/GherXunit.Core/Samples/Features/SubscriptionTest.Steps.cs
similarity index 100%
rename from src/base/GherXunit.Core/Features/SubscriptionTest.Steps.cs
rename to src/base/GherXunit.Core/Samples/Features/SubscriptionTest.Steps.cs
diff --git a/src/base/GherXunit.Core/Features/SubscriptionTest.cs b/src/base/GherXunit.Core/Samples/Features/SubscriptionTest.cs
similarity index 100%
rename from src/base/GherXunit.Core/Features/SubscriptionTest.cs
rename to src/base/GherXunit.Core/Samples/Features/SubscriptionTest.cs
diff --git a/src/sample/BddSample/Samples/Features/SubscriptionTest.Steps.cs b/src/base/GherXunit.Core/Samples/Localization/LocalizationTest.Steps.cs
similarity index 71%
rename from src/sample/BddSample/Samples/Features/SubscriptionTest.Steps.cs
rename to src/base/GherXunit.Core/Samples/Localization/LocalizationTest.Steps.cs
index 147f7d1..b4f13ea 100644
--- a/src/sample/BddSample/Samples/Features/SubscriptionTest.Steps.cs
+++ b/src/base/GherXunit.Core/Samples/Localization/LocalizationTest.Steps.cs
@@ -1,9 +1,9 @@
using GherXunit.Annotations;
using Xunit.Abstractions;
-namespace BddTests.Samples.Features;
+namespace BddTests.Samples.Localization;
-public partial class SubscriptionTest(ITestOutputHelper output): IGherXunit
+public partial class LocalizationTest(ITestOutputHelper output): IGherXunit
{
public ITestOutputHelper Output { get; } = output;
private void WhenPattyLogsSteps() => Assert.True(true);
diff --git a/src/base/GherXunit.Core/Samples/Localization/LocalizationTest.cs b/src/base/GherXunit.Core/Samples/Localization/LocalizationTest.cs
new file mode 100644
index 0000000..9863c04
--- /dev/null
+++ b/src/base/GherXunit.Core/Samples/Localization/LocalizationTest.cs
@@ -0,0 +1,39 @@
+using GherXunit.Annotations;
+
+namespace BddTests.Samples.Localization;
+
+[Feature("Subscribers see different articles based on their subscription level")]
+public partial class LocalizationTest
+{
+ [Scenario("Inscrever-se para ver artigos gratuitos")]
+ async Task WhenFriedaLogs() => await this.ExecuteAscync(
+ refer: WhenFriedaLogsSteps,
+ lexer: Lexers.PtBr,
+ steps: """
+ Dado Free Frieda possui uma assinatura gratuita
+ Quando Free Frieda faz login com suas credenciais válidas
+ Então ela vê um artigo gratuito
+ """);
+
+ [Scenario("Subscriber with a paid subscription can access both free and paid articles")]
+ void WhenPattyLogs() => this.Execute(
+ refer: WhenPattyLogsSteps,
+ lexer: new EmojiGherXunitLexer(),
+ steps: """
+ Given Paid Patty has a basic-level paid subscription
+ When Paid Patty logs in with her valid credentials
+ Then she sees a Free article and a Paid article
+ """);
+}
+
+// Custom lexer for emojis
+public record EmojiGherXunitLexer : IGherXunitLexer
+{
+ public (string Key, string Value)[] Given => [("Given", "\ud83d\ude10")];
+ public (string Key, string Value)[] When => [("When", "\ud83c\udfac")];
+ public (string Key, string Value)[] Then => [("Then", "\ud83d\ude4f")];
+ public (string Key, string Value)[] And => [("And", "\ud83d\ude02")];
+ public string Background => "\ud83d\udca4";
+ public string Scenario => "\ud83e\udd52\ud83d\udcd5";
+ public string Feature => "\ud83d\udcda";
+}
\ No newline at end of file
diff --git a/src/sample/BddSample/Samples/Outline/ScenarioOutlineTest.Steps.cs b/src/base/GherXunit.Core/Samples/Outline/ScenarioOutlineTest.Steps.cs
similarity index 100%
rename from src/sample/BddSample/Samples/Outline/ScenarioOutlineTest.Steps.cs
rename to src/base/GherXunit.Core/Samples/Outline/ScenarioOutlineTest.Steps.cs
diff --git a/src/sample/BddSample/Samples/Outline/ScenarioOutlineTest.cs b/src/base/GherXunit.Core/Samples/Outline/ScenarioOutlineTest.cs
similarity index 100%
rename from src/sample/BddSample/Samples/Outline/ScenarioOutlineTest.cs
rename to src/base/GherXunit.Core/Samples/Outline/ScenarioOutlineTest.cs
diff --git a/src/sample/BddSample/Samples/Refactoring/ExemploA/ProcessamentoServiceTests.cs b/src/base/GherXunit.Core/Samples/Refactoring/ExemploA/ProcessamentoServiceTests.cs
similarity index 70%
rename from src/sample/BddSample/Samples/Refactoring/ExemploA/ProcessamentoServiceTests.cs
rename to src/base/GherXunit.Core/Samples/Refactoring/ExemploA/ProcessamentoServiceTests.cs
index 47907d8..bbfdc3f 100644
--- a/src/sample/BddSample/Samples/Refactoring/ExemploA/ProcessamentoServiceTests.cs
+++ b/src/base/GherXunit.Core/Samples/Refactoring/ExemploA/ProcessamentoServiceTests.cs
@@ -28,13 +28,13 @@ And a confirmation message is logged
public partial class DataProcessingServiceTests(ITestOutputHelper output) : IGherXunit
{
- private Mock _apiClientMock;
- private Mock _repositoryMock;
- private Mock _queueServiceMock;
- private Mock> _loggerMock;
- private DataProcessingService _dataProcessingService;
+ private Mock? _apiClientMock;
+ private Mock? _repositoryMock;
+ private Mock? _queueServiceMock;
+ private Mock>? _loggerMock;
+ private DataProcessingService? _dataProcessingService;
- public ITestOutputHelper? Output { get; } = output;
+ public ITestOutputHelper Output { get; } = output;
private Task Setup()
{
@@ -57,30 +57,30 @@ private async Task ProcessData_ShouldProcessSuccessfully()
// Arrange
var data = new Data { Value = "Test" };
- _apiClientMock.Setup(api => api.FetchDataAsync())
+ _apiClientMock?.Setup(api => api.FetchDataAsync())
.ReturnsAsync(data);
- _repositoryMock.Setup(repo => repo.SaveDataAsync(data))
+ _repositoryMock?.Setup(repo => repo.SaveDataAsync(data))
.Returns(Task.CompletedTask);
- _queueServiceMock.Setup(queue => queue.PublishMessage(data.Value))
+ _queueServiceMock?.Setup(queue => queue.PublishMessage(data.Value))
.Returns(Task.CompletedTask);
// Act
- await _dataProcessingService.ProcessData();
+ await _dataProcessingService?.ProcessData()!;
// Assert
- _apiClientMock.Verify(api => api.FetchDataAsync(), Times.Once);
- _repositoryMock.Verify(repo => repo.SaveDataAsync(data), Times.Once);
- _queueServiceMock.Verify(queue => queue.PublishMessage(data.Value), Times.Once);
+ _apiClientMock?.Verify(api => api.FetchDataAsync(), Times.Once);
+ _repositoryMock?.Verify(repo => repo.SaveDataAsync(data), Times.Once);
+ _queueServiceMock?.Verify(queue => queue.PublishMessage(data.Value), Times.Once);
- _loggerMock.Verify(
+ _loggerMock?.Verify(
log => log.Log(
LogLevel.Information,
It.IsAny(),
- It.Is((v, t) => v.ToString().Contains("Processing completed")),
+ It.Is((v, t) => v.ToString()!.Contains("Processing completed")),
null,
- It.IsAny>()
+ It.IsAny>()!
), Times.Once);
}
@@ -88,22 +88,22 @@ private async Task ProcessData_ShouldProcessSuccessfully()
public async Task ProcessData_ShouldThrowExceptionWhenApiFails()
{
// Arrange
- _apiClientMock.Setup(api => api.FetchDataAsync())
+ _apiClientMock?.Setup(api => api.FetchDataAsync())
.ThrowsAsync(new HttpRequestException("API failure"));
// Act & Assert
- await Assert.ThrowsAsync(() => _dataProcessingService.ProcessData());
+ await Assert.ThrowsAsync(() => _dataProcessingService!.ProcessData());
- _repositoryMock.Verify(repo => repo.SaveDataAsync(It.IsAny()), Times.Never);
- _queueServiceMock.Verify(queue => queue.PublishMessage(It.IsAny()), Times.Never);
+ _repositoryMock?.Verify(repo => repo.SaveDataAsync(It.IsAny()), Times.Never);
+ _queueServiceMock?.Verify(queue => queue.PublishMessage(It.IsAny()), Times.Never);
- _loggerMock.Verify(
+ _loggerMock?.Verify(
log => log.Log(
LogLevel.Error,
It.IsAny(),
- It.Is((v, t) => v.ToString().Contains("Error fetching data from API")),
+ It.Is((v, t) => v.ToString()!.Contains("Error fetching data from API")),
It.IsAny(),
- It.IsAny>()
+ It.IsAny>()!
), Times.Once);
}
@@ -113,24 +113,24 @@ public async Task ProcessData_ShouldThrowExceptionWhenDatabaseFails()
// Arrange
var data = new Data { Value = "Test" };
- _apiClientMock.Setup(api => api.FetchDataAsync())
+ _apiClientMock?.Setup(api => api.FetchDataAsync())
.ReturnsAsync(data);
- _repositoryMock.Setup(repo => repo.SaveDataAsync(data))
+ _repositoryMock?.Setup(repo => repo.SaveDataAsync(data))
.ThrowsAsync(new Exception("Database failure"));
// Act & Assert
- await Assert.ThrowsAsync(() => _dataProcessingService.ProcessData());
+ await Assert.ThrowsAsync(() => _dataProcessingService!.ProcessData());
- _queueServiceMock.Verify(queue => queue.PublishMessage(It.IsAny()), Times.Never);
+ _queueServiceMock?.Verify(queue => queue.PublishMessage(It.IsAny()), Times.Never);
- _loggerMock.Verify(
+ _loggerMock?.Verify(
log => log.Log(
LogLevel.Error,
It.IsAny(),
- It.Is((v, t) => v.ToString().Contains("Error saving data to the database")),
+ It.Is((v, t) => v.ToString()!.Contains("Error saving data to the database")),
It.IsAny(),
- It.IsAny>()
+ It.IsAny>()!
), Times.Once);
}
@@ -140,25 +140,25 @@ public async Task ProcessData_ShouldThrowExceptionWhenQueueFails()
// Arrange
var data = new Data { Value = "Test" };
- _apiClientMock.Setup(api => api.FetchDataAsync())
+ _apiClientMock?.Setup(api => api.FetchDataAsync())
.ReturnsAsync(data);
- _repositoryMock.Setup(repo => repo.SaveDataAsync(data))
+ _repositoryMock?.Setup(repo => repo.SaveDataAsync(data))
.Returns(Task.CompletedTask);
- _queueServiceMock.Setup(queue => queue.PublishMessage(data.Value))
+ _queueServiceMock?.Setup(queue => queue.PublishMessage(data.Value))
.ThrowsAsync(new Exception("Queue failure"));
// Act & Assert
- await Assert.ThrowsAsync(() => _dataProcessingService.ProcessData());
+ await Assert.ThrowsAsync(() => _dataProcessingService!.ProcessData());
- _loggerMock.Verify(
+ _loggerMock?.Verify(
log => log.Log(
LogLevel.Error,
It.IsAny(),
- It.Is((v, t) => v.ToString().Contains("Error publishing message to the queue")),
+ It.Is((v, t) => v.ToString()!.Contains("Error publishing message to the queue")),
It.IsAny(),
- It.IsAny>()
+ It.IsAny>()!
), Times.Once);
}
diff --git a/src/sample/BddSample/Samples/Rules/RuleTest.Steps.cs b/src/base/GherXunit.Core/Samples/Rules/RuleTest.Steps.cs
similarity index 100%
rename from src/sample/BddSample/Samples/Rules/RuleTest.Steps.cs
rename to src/base/GherXunit.Core/Samples/Rules/RuleTest.Steps.cs
diff --git a/src/sample/BddSample/Samples/Rules/RuleTest.cs b/src/base/GherXunit.Core/Samples/Rules/RuleTest.cs
similarity index 100%
rename from src/sample/BddSample/Samples/Rules/RuleTest.cs
rename to src/base/GherXunit.Core/Samples/Rules/RuleTest.cs
diff --git a/src/base/GherXunit.Core/StepStringHandler.cs b/src/base/GherXunit.Core/StepStringHandler.cs
deleted file mode 100644
index 45e2c02..0000000
--- a/src/base/GherXunit.Core/StepStringHandler.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-#nullable enable
-using System.Runtime.CompilerServices;
-
-namespace GherXunit.Annotations;
-
-[InterpolatedStringHandler]
-public ref struct StepStringHandler()
-{
- private string _message = "";
-
- public void AppendLiteral(string s) => _message += HighlightKeyword(s);
- public void AppendFormatted(T value) => _message += value?.ToString();
- public override string ToString() => _message;
-
- private string HighlightKeyword(string input)
- {
- return input
- .Replace("Feature", $"{"\u2937 FEATURE",8}")
- .Replace("Scenario", $"{"\u2937 SCENARIO",13}")
- .Replace("Background", $"{"\u2937 BACKGROUND",15}")
- .Replace("Given", $"{"|",7} {"GIVEN",5} \u2198")
- .Replace("When", $"{"|",7} {"WHEN" ,5} \u2198")
- .Replace("Then", $"{"|",7} {"THEN" ,5} \u2198")
- .Replace("And", $"{"|",7} {"AND" ,5} \u2198");
- }
-}
\ No newline at end of file
diff --git a/src/base/GherXunit.Core/StringHandler.cs b/src/base/GherXunit.Core/StringHandler.cs
new file mode 100644
index 0000000..b1ed3ea
--- /dev/null
+++ b/src/base/GherXunit.Core/StringHandler.cs
@@ -0,0 +1,64 @@
+#nullable enable
+using System.Runtime.CompilerServices;
+
+namespace GherXunit.Annotations;
+
+[InterpolatedStringHandler]
+public class StringHandler(IGherXunitLexer lexer)
+{
+ private string _message = "";
+
+ public void AppendLiteral(string s) => _message += HighlightKeyword(s);
+ public override string ToString() => _message;
+
+ private string HighlightKeyword(string input)
+ {
+ int[] words =
+ [
+ lexer.Given.Max(x => x.Value.Length),
+ lexer.When.Max(x => x.Value.Length),
+ lexer.Then.Max(x => x.Value.Length),
+ lexer.And.Max(x => x.Value.Length)
+ ];
+
+ var max = words.Max() + 1;
+
+ lexer.Given.ToList().ForEach(x => input = input.Replace($"\n{x.Key}", $"\n{"|",5}{x.Value.PadLeft(max)} \u2198"));
+ lexer.When.ToList().ForEach(x => input = input.Replace($"\n{x.Key}", $"\n{"|",5}{x.Value.PadLeft(max)} \u2198"));
+ lexer.Then.ToList().ForEach(x => input = input.Replace($"\n{x.Key}", $"\n{"|",5}{x.Value.PadLeft(max)} \u2198"));
+ lexer.And.ToList().ForEach(x => input = input.Replace($"\n{x.Key}", $"\n{"|",5}{x.Value.PadLeft(max)} \u2198"));
+
+ return input
+ .Replace(nameof(lexer.Feature), $"\u2937 {lexer.Feature}")
+ .Replace(nameof(lexer.Scenario), $"{"\u2937",3} {lexer.Scenario}")
+ .Replace(nameof(lexer.Background), $"{"\u2937",3} {lexer.Background}");
+ }
+}
+
+public static class Lexers
+{
+ public static IGherXunitLexer EnUs => new DefaultGherXunitLexer();
+ public static IGherXunitLexer PtBr => new PtBrGherXunitLexer();
+}
+
+public record DefaultGherXunitLexer : IGherXunitLexer
+{
+ public (string Key, string Value)[] Given => [("Given", "GIVEN")];
+ public (string Key, string Value)[] When => [("When", "WHEN")];
+ public (string Key, string Value)[] Then => [("Then", "THEN")];
+ public (string Key, string Value)[] And => [("And", "AND")];
+ public string Background => "BACKGROUND";
+ public string Scenario => "SCENARIO";
+ public string Feature => "FEATURE";
+}
+
+public record PtBrGherXunitLexer : IGherXunitLexer
+{
+ public (string Key, string Value)[] Given => [("Dado", "DADO"), ("Dada", "DADA"), ("Dados", "DADOS"), ("Dadas", "DADAS")];
+ public (string Key, string Value)[] When => [("Quando", "QUANDO")];
+ public (string Key, string Value)[] Then => [("Então", "ENTÃO"), ("Entao", "ENTAO")];
+ public (string Key, string Value)[] And => [("E", "E")];
+ public string Background => "CONTEXTO";
+ public string Scenario => "CENARIO";
+ public string Feature => "FUNCIONALIDADE";
+}
\ No newline at end of file
diff --git a/src/lib/GherXunit/GherXunit.Content.Interfaces.cs b/src/lib/GherXunit/GherXunit.Content.Interfaces.cs
index 068568f..f61b8bb 100644
--- a/src/lib/GherXunit/GherXunit.Content.Interfaces.cs
+++ b/src/lib/GherXunit/GherXunit.Content.Interfaces.cs
@@ -28,5 +28,17 @@ public interface IGherXunitOutputProvider
{
public ITestOutputHelper Output { get; }
}
+
+ //Lexer
+ public interface IGherXunitLexer
+ {
+ public (string Key, string Value)[] Given { get; }
+ public (string Key, string Value)[] When { get; }
+ public (string Key, string Value)[] Then { get; }
+ public (string Key, string Value)[] And { get; }
+ public string Background { get; }
+ public string Scenario { get; }
+ public string Feature { get; }
+ }
""";
}
\ No newline at end of file
diff --git a/src/lib/GherXunit/GherXunit.Content.Methods.cs b/src/lib/GherXunit/GherXunit.Content.Methods.cs
index 2f95d73..bce9838 100644
--- a/src/lib/GherXunit/GherXunit.Content.Methods.cs
+++ b/src/lib/GherXunit/GherXunit.Content.Methods.cs
@@ -12,59 +12,57 @@ public struct GherXunitMethods
using System.Reflection;
using Xunit.Abstractions;
using Xunit.Sdk;
-
+
namespace GherXunit.Annotations;
-
+
public static class GherXunitSteps
{
- // Async methods
- public static async Task BackgroundAsync(this IGherXunitStep scenario, Delegate refer, string steps) => await ExecuteAscync(scenario, refer.Method, steps, true);
- public static async Task ExecuteAscync(this IGherXunitStep scenario, string steps) => await ExecuteAscync(scenario, null, steps, false);
- public static async Task ExecuteAscync(this IGherXunitStep scenario, Delegate refer, string steps) => await ExecuteAscync(scenario, refer.Method, steps);
- public static async Task ExecuteAscync(this IGherXunitStep scenario, Delegate refer, object[] param, string steps) => await ExecuteAscync(scenario, refer.Method, steps, false, param);
- public static async Task NonExecutableAsync(this IGherXunitStep scenario, string? steps = null) => await ExecuteAscync(scenario, null, steps, false);
-
- // Sync methods
- public static void Background(this IGherXunitStep scenario, Delegate refer, string steps) => Execute(scenario, refer.Method, steps, true);
- public static void Execute(this IGherXunitStep scenario, string steps) => Execute(scenario, null, steps, false);
- public static void Execute(this IGherXunitStep scenario, Delegate refer, string steps) => Execute(scenario, refer.Method, steps);
- public static void Execute(this IGherXunitStep scenario, Delegate refer, object[] param, string steps) => Execute(scenario, refer.Method, steps, false, param);
- public static void NonExecutable(this IGherXunitStep feature, string? steps) => Execute(feature, null, steps, false, []);
+ // Background methods
+ public static void Background(this IGherXunitStep scenario, Delegate refer, string steps, IGherXunitLexer? lexer = null) => InternalExecute(scenario, refer.Method, steps, true, lexer);
+ public static async Task BackgroundAsync(this IGherXunitStep scenario, Delegate refer, string steps, IGherXunitLexer? lexer = null) => await InternalExecuteAscync(scenario, refer.Method, steps, true, lexer);
+
+ // Execute methods
+ public static void Execute(this IGherXunitStep scenario, string steps, Delegate? refer = null, object[]? param = null, IGherXunitLexer? lexer = null) => InternalExecute(scenario, refer?.Method, steps, false, lexer, param);
+ public static async Task ExecuteAscync(this IGherXunitStep scenario, string steps, Delegate? refer = null, object[]? param = null, IGherXunitLexer? lexer = null) => await InternalExecuteAscync(scenario, refer?.Method, steps, false, lexer, param);
+
+ // Non Executable
+ public static void NonExecutable(this IGherXunitStep feature, string steps, IGherXunitLexer? lexer = null) => InternalExecute(feature, null, steps, false, lexer);
+ public static async Task NonExecutableAsync(this IGherXunitStep scenario, string steps, IGherXunitLexer? lexer = null) => await InternalExecuteAscync(scenario, null, steps, false, lexer);
// Private methods
- private static void Execute(this IGherXunitStep scenario, MethodInfo? method, string? steps,
- bool isBackground = false, params object?[] param)
+ private static void InternalExecute(this IGherXunitStep scenario, MethodInfo? method, string? steps,
+ bool isBackground = false, IGherXunitLexer? lexer = null, params object[]? param)
{
try
{
method?.Invoke(scenario, param);
- scenario.Write(method?.Name, steps, false, isBackground);
+ scenario.Write(method?.Name, steps, false, isBackground, lexer);
}
catch (Exception)
{
- scenario.Write(method?.Name, steps, true, isBackground);
+ scenario.Write(method?.Name, steps, true, isBackground, lexer);
throw;
}
}
- private static async Task ExecuteAscync(this IGherXunitStep scenario, MethodInfo? method, string? steps,
- bool isBackground = false, params object?[] param)
+ private static async Task InternalExecuteAscync(this IGherXunitStep scenario, MethodInfo? method, string? steps,
+ bool isBackground = false, IGherXunitLexer? lexer = null, params object[]? param)
{
try
{
var task = method is null ? Task.CompletedTask : (Task)method.Invoke(scenario, param)!;
await task;
- scenario.Write(method?.Name, steps, false, isBackground);
+ scenario.Write(method?.Name, steps, false, isBackground, lexer);
}
catch (Exception)
{
- scenario.Write(method?.Name, steps, true, isBackground);
+ scenario.Write(method?.Name, steps, true, isBackground, lexer);
throw;
}
}
- private static void Write(this IGherXunitStep scenario, string? methodName, string? steps, bool isException = false, bool isBackground = false)
+ private static void Write(this IGherXunitStep scenario, string? methodName, string? steps, bool isException = false, bool isBackground = false, IGherXunitLexer? lexer = null)
{
if (steps is null) return;
@@ -75,8 +73,8 @@ private static void Write(this IGherXunitStep scenario, string? methodName, stri
var scenarioText = iTest is null
? $"{(isBackground ? "Background" : "Scenario")} {methodName}\r\n"
: $"{(isBackground ? "Background" : "Scenario")} {iTest.DisplayName}\r\n";
-
- var stepString = new StepStringHandler();
+
+ var stepString = new StringHandler(lexer ?? Lexers.Default);
stepString.AppendLiteral($"{statusResult}{featuresText}{scenarioText}{steps}");
output?.WriteLine(".");
diff --git a/src/lib/GherXunit/GherXunit.Content.StringHandler.cs b/src/lib/GherXunit/GherXunit.Content.StringHandler.cs
index e67efe3..99cf2a0 100644
--- a/src/lib/GherXunit/GherXunit.Content.StringHandler.cs
+++ b/src/lib/GherXunit/GherXunit.Content.StringHandler.cs
@@ -10,25 +10,63 @@ public struct GherXunitStepStringHandler
namespace GherXunit.Annotations;
[InterpolatedStringHandler]
- public ref struct StepStringHandler()
+ public class StringHandler(IGherXunitLexer lexer)
{
private string _message = "";
public void AppendLiteral(string s) => _message += HighlightKeyword(s);
- public void AppendFormatted(T value) => _message += value?.ToString();
public override string ToString() => _message;
private string HighlightKeyword(string input)
{
+ int[] words =
+ [
+ lexer.Given.Max(x => x.Value.Length),
+ lexer.When.Max(x => x.Value.Length),
+ lexer.Then.Max(x => x.Value.Length),
+ lexer.And.Max(x => x.Value.Length)
+ ];
+
+ var max = words.Max() + 1;
+
+ lexer.Given.ToList().ForEach(x => input = input.Replace($"\n{x.Key}", $"\n{"|",5}{x.Value.PadLeft(max)} \u2198"));
+ lexer.When.ToList().ForEach(x => input = input.Replace($"\n{x.Key}", $"\n{"|",5}{x.Value.PadLeft(max)} \u2198"));
+ lexer.Then.ToList().ForEach(x => input = input.Replace($"\n{x.Key}", $"\n{"|",5}{x.Value.PadLeft(max)} \u2198"));
+ lexer.And.ToList().ForEach(x => input = input.Replace($"\n{x.Key}", $"\n{"|",5}{x.Value.PadLeft(max)} \u2198"));
+
return input
- .Replace("Feature", $"{"\u2937 FEATURE",8}")
- .Replace("Scenario", $"{"\u2937 SCENARIO",13}")
- .Replace("Background", $"{"\u2937 BACKGROUND",15}")
- .Replace("Given", $"{"|",7} {"GIVEN",5} \u2198")
- .Replace("When", $"{"|",7} {"WHEN" ,5} \u2198")
- .Replace("Then", $"{"|",7} {"THEN" ,5} \u2198")
- .Replace("And", $"{"|",7} {"AND" ,5} \u2198");
+ .Replace(nameof(lexer.Feature), $"\u2937 {lexer.Feature}")
+ .Replace(nameof(lexer.Scenario), $"{"\u2937",3} {lexer.Scenario}")
+ .Replace(nameof(lexer.Background), $"{"\u2937",3} {lexer.Background}");
}
}
+
+ public static class Lexers
+ {
+ public static IGherXunitLexer Default => new DefaultGherXunitLexer();
+ public static IGherXunitLexer PtBr => new PtBrGherXunitLexer();
+ }
+
+ public record DefaultGherXunitLexer : IGherXunitLexer
+ {
+ public (string Key, string Value)[] Given => [("Given", "GIVEN")];
+ public (string Key, string Value)[] When => [("When", "WHEN")];
+ public (string Key, string Value)[] Then => [("Then", "THEN")];
+ public (string Key, string Value)[] And => [("And", "AND")];
+ public string Background => "BACKGROUND";
+ public string Scenario => "SCENARIO";
+ public string Feature => "FEATURE";
+ }
+
+ public record PtBrGherXunitLexer : IGherXunitLexer
+ {
+ public (string Key, string Value)[] Given => [("Dado", "DADO"), ("Dada", "DADA"), ("Dados", "DADOS"), ("Dadas", "DADAS")];
+ public (string Key, string Value)[] When => [("Quando", "QUANDO")];
+ public (string Key, string Value)[] Then => [("Então", "ENTÃO"), ("Entao", "ENTAO")];
+ public (string Key, string Value)[] And => [("E", "E")];
+ public string Background => "CONTEXTO";
+ public string Scenario => "CENARIO";
+ public string Feature => "FUNCIONALIDADE";
+ }
""";
}
\ No newline at end of file
diff --git a/src/sample/BddSample/BddSample.csproj b/src/sample/BddSample/BddSample.csproj
deleted file mode 100644
index a741bc2..0000000
--- a/src/sample/BddSample/BddSample.csproj
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
- net9.0
- enable
- enable
- false
- BddTests
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/sample/BddSample/Samples/Backgrounds/BackgroundTest.Context.cs b/src/sample/BddSample/Samples/Backgrounds/BackgroundTest.Context.cs
deleted file mode 100644
index b060502..0000000
--- a/src/sample/BddSample/Samples/Backgrounds/BackgroundTest.Context.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace BddTests.Samples.Backgrounds;
-
-public class BackgroundContext
-{
- public string ContextId { get; } = Guid.NewGuid().ToString();
- public Dictionary OwnersAndBlogs { get; } = new();
-
- public BackgroundContext()
- {
- OwnersAndBlogs.Add("Greg", "Greg's anti-tax rants");
- OwnersAndBlogs.Add("Dr. Bill", "Expensive Therapy");
- }
-}
\ No newline at end of file
diff --git a/src/sample/BddSample/Samples/Backgrounds/BackgroundTest.Steps.cs b/src/sample/BddSample/Samples/Backgrounds/BackgroundTest.Steps.cs
deleted file mode 100644
index 3760b31..0000000
--- a/src/sample/BddSample/Samples/Backgrounds/BackgroundTest.Steps.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using System.Runtime.CompilerServices;
-using GherXunit.Annotations;
-using Xunit.Abstractions;
-
-namespace BddTests.Samples.Backgrounds;
-
-public partial class BackgroundTest(ITestOutputHelper output) : IGherXunit, IAsyncLifetime
-{
- public ITestOutputHelper Output { get; } = output;
- private BackgroundContext? Context { get; set; }
-
- private Task Setup()
- {
- Context = new BackgroundContext();
- return Task.CompletedTask;
- }
-
- private async Task DrBillPostToBlogStep()
- {
- var result = await PostToBlog("Dr. Bill", "Expensive Therapy");
- Assert.Equal("Your article was published.", result);
- }
-
- private async Task DrBillPostToBlogFailStep()
- {
- var result = await PostToBlog("Dr. Bill", "Greg's anti-tax rants");
- Assert.Equal("Hey! That's not your blog!", result);
- }
-
- private async Task GregPostToBlogStep()
- {
- var result = await PostToBlog("Greg", "Greg's anti-tax rants");
- Assert.Equal("Your article was published.", result);
- }
-
- private async Task PostToBlog(string owner, string blog)
- {
- if (!Context!.OwnersAndBlogs.TryGetValue(owner, out string? value) || value != blog)
- return "Hey! That's not your blog!";
-
- await Task.Yield();
- return "Your article was published.";
- }
-
- public Task DisposeAsync()
- {
- return Task.CompletedTask;
- }
-}
\ No newline at end of file
diff --git a/src/sample/BddSample/Samples/Backgrounds/BackgroundTest.cs b/src/sample/BddSample/Samples/Backgrounds/BackgroundTest.cs
deleted file mode 100644
index d0b13d0..0000000
--- a/src/sample/BddSample/Samples/Backgrounds/BackgroundTest.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using GherXunit.Annotations;
-using Xunit.Abstractions;
-
-namespace BddTests.Samples.Backgrounds;
-
-[Feature("Multiple site support Only blog owners can post to a blog, except administrators, who can post to all blogs.")]
-public partial class BackgroundTest
-{
- [Background]
- public async Task InitializeAsync() => await this.BackgroundAsync(
- refer: Setup,
- steps: """
- Given a global administrator named <<"Greg">>
- And a blog named <<"Greg's anti-tax rants">>
- And a customer named <<"Dr. Bill">>
- And a blog named <<"Expensive Therapy">> owned by <<"Dr. Bill">>
- """);
-
- [Scenario("Dr. Bill posts to his own blog")]
- public async Task DrBillPostToBlog() => await this.ExecuteAscync(
- refer: DrBillPostToBlogStep,
- steps: """
- Given I am logged in as Dr. Bill
- When I try to post to "Expensive Therapy"
- Then I should see "Your article was published."
- """);
-
- [Scenario("Dr. Bill tries to post to somebody else's blog, and fails")]
- public async Task DrBillPostToBlogFail() => await this.ExecuteAscync(
- refer: DrBillPostToBlogFailStep,
- steps: """
- Given I am logged in as Dr. Bill
- When I try to post to "Greg's anti-tax rants"
- Then I should see "Hey! That's not your blog!"
- """);
-
- [Scenario("Greg posts to a client's blog")]
- public async Task GregPostToBlog() => await this.ExecuteAscync(
- refer: GregPostToBlogStep,
- steps: """
- Given I am logged in as Greg
- When I try to post to "Expensive Therapy"
- Then I should see "Your article was published."
- """);
-}
\ No newline at end of file
diff --git a/src/sample/BddSample/Samples/Features/SubscriptionTest.cs b/src/sample/BddSample/Samples/Features/SubscriptionTest.cs
deleted file mode 100644
index 452cc1a..0000000
--- a/src/sample/BddSample/Samples/Features/SubscriptionTest.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using GherXunit.Annotations;
-
-namespace BddTests.Samples.Features;
-
-[Feature("Subscribers see different articles based on their subscription level")]
-public partial class SubscriptionTest
-{
- [Scenario("Free subscribers see only the free articles")]
- async Task WhenFriedaLogs() => await this.ExecuteAscync(
- refer: WhenFriedaLogsSteps,
- steps: """
- Given Free Frieda has a free subscription
- When Free Frieda logs in with her valid credentials
- Then she sees a Free article
- """);
-
- [Scenario("Subscriber with a paid subscription can access both free and paid articles")]
- void WhenPattyLogs() => this.Execute(
- refer: WhenPattyLogsSteps,
- steps: """
- Given Paid Patty has a basic-level paid subscription
- When Paid Patty logs in with her valid credentials
- Then she sees a Free article and a Paid article
- """);
-}
\ No newline at end of file