Skip to content
Merged
9 changes: 9 additions & 0 deletions CapMonsterCloud.Client.IntegrationTests/Gen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ public static List<T> ListOfValues<T>(Func<T> createFunc, int count)
return Enumerable.Repeat(0, count).Select(x => createFunc()).ToList();
}

public static T[] ArrayOfValues<T>(Func<T> createFunc) =>
ArrayOfValues(createFunc, 5);

public static T[] ArrayOfValues<T>(Func<T> createFunc, int count)
{
if (count <= 0) throw new ArgumentOutOfRangeException(nameof(count));
return Enumerable.Repeat(0, count).Select(x => createFunc()).ToArray();
}

public static bool RandomBool() => Rnd.NextDouble() >= 0.5;

public static string RandomGuid()
Expand Down
204 changes: 196 additions & 8 deletions CapMonsterCloud.Client.IntegrationTests/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -465,14 +465,60 @@
actual.Should().BeEquivalentTo(expectedResult);
}

[Test]
public async Task Imperva_ShouldSolve()
{
var clientKey = Gen.RandomString();
var taskId = Gen.RandomInt();

var captchaRequest = ObjectGen.CustomTask.CreateImpervaTask();
var expectedResult = ObjectGen.CustomTask.CreateImpervaSolution();

var expectedRequests = new List<(RequestType Type, string ExpectedRequest)>
{
(
Type: RequestType.CreateTask,
ExpectedRequest: JsonConvert.SerializeObject(new
{ clientKey = clientKey, task = captchaRequest, softId = 53 })
),
(
Type: RequestType.GetTaskResult,
ExpectedRequest: JsonConvert.SerializeObject(new { clientKey = clientKey, taskId = taskId })
),
};

var captchaResults = new List<object>
{
new { taskId = taskId, errorId = 0, errorCode = (string)null! },
new
{
status = "ready",
solution = new
{
domains = expectedResult.Solution.Domains
},
errorId = 0,
errorCode = (string)null!
}
};

var sut = new Sut(clientKey);
sut.SetupHttpServer(captchaResults);

var actual = await sut.SolveAsync(captchaRequest);

sut.GetActualRequests().Should().BeEquivalentTo(expectedRequests);
actual.Should().BeEquivalentTo(expectedResult);
}

[Test]
public async Task RecaptchaComplexImageTask_ShouldSolve()
{
var clientKey = Gen.RandomString();
var taskId = Gen.RandomInt();

var captchaRequest = ObjectGen.ComplexImageTask.CreateRecaptchaComplexImageTask();
var expectedResult = ObjectGen.ComplexImageTask.CreateSolution();
var expectedResult = ObjectGen.ComplexImageTask.CreateGridComplexImageTaskSolution();

var expectedRequests = new List<(RequestType Type, string ExpectedRequest)>
{
Expand Down Expand Up @@ -512,13 +558,13 @@
}

[Test]
public async Task HCaptchaComplexImageTask_ShouldSolve()
public async Task HCaptchaComplexImageTaskWithNumericAnswer_ShouldSolve()
{
var clientKey = Gen.RandomString();
var taskId = Gen.RandomInt();

var captchaRequest = ObjectGen.ComplexImageTask.CreateHCaptchaComplexImageTask();
var expectedResult = ObjectGen.ComplexImageTask.CreateSolution();
var expectedResult = ObjectGen.ComplexImageTask.CreateDynamicComplexImageTaskSolutionWithNumericAnswer();

var expectedRequests = new List<(RequestType Type, string ExpectedRequest)>
{
Expand All @@ -541,7 +587,8 @@
status = "ready",
solution = new
{
answer = expectedResult.Solution.Answer
answer = expectedResult.Solution.Answer.NumericAnswer,
metadata = new { AnswerType = "NumericArray" }
},
errorId = 0,
errorCode = (string)null!
Expand All @@ -555,16 +602,63 @@

sut.GetActualRequests().Should().BeEquivalentTo(expectedRequests);
actual.Should().BeEquivalentTo(expectedResult);
}

}

[Test]
public async Task HCaptchaComplexImageTaskWithGridAnswer_ShouldSolve()
{
var clientKey = Gen.RandomString();
var taskId = Gen.RandomInt();

var captchaRequest = ObjectGen.ComplexImageTask.CreateHCaptchaComplexImageTask();
var expectedResult = ObjectGen.ComplexImageTask.CreateDynamicComplexImageTaskSolutionWithGridAnswer();

var expectedRequests = new List<(RequestType Type, string ExpectedRequest)>
{
(
Type: RequestType.CreateTask,
ExpectedRequest: JsonConvert.SerializeObject(new
{ clientKey = clientKey, task = captchaRequest, softId = 53 })
),
(
Type: RequestType.GetTaskResult,
ExpectedRequest: JsonConvert.SerializeObject(new { clientKey = clientKey, taskId = taskId })
),
};

var captchaResults = new List<object>
{
new { taskId = taskId, errorId = 0, errorCode = (string)null! },
new
{
status = "ready",
solution = new
{
answer = expectedResult.Solution.Answer.GridAnswer,
metadata = new { AnswerType = "Grid" }
},
errorId = 0,
errorCode = (string)null!
}
};

var sut = new Sut(clientKey);
sut.SetupHttpServer(captchaResults);

var actual = await sut.SolveAsync(captchaRequest);

sut.GetActualRequests().Should().BeEquivalentTo(expectedRequests);
actual.Should().BeEquivalentTo(expectedResult);
}

[Test]
public async Task FunCaptchaComplexImageTask_ShouldSolve()
{
var clientKey = Gen.RandomString();
var taskId = Gen.RandomInt();

var captchaRequest = ObjectGen.ComplexImageTask.CreateFunCaptchaComplexImageTask();
var expectedResult = ObjectGen.ComplexImageTask.CreateSolution();
var expectedResult = ObjectGen.ComplexImageTask.CreateGridComplexImageTaskSolution();

var expectedRequests = new List<(RequestType Type, string ExpectedRequest)>
{
Expand Down Expand Up @@ -602,7 +696,101 @@
sut.GetActualRequests().Should().BeEquivalentTo(expectedRequests);
actual.Should().BeEquivalentTo(expectedResult);
}


[Test]
public async Task RecognitionComplexImageTaskWithGridAnswer_ShouldSolve()
{
var clientKey = Gen.RandomString();
var taskId = Gen.RandomInt();

var captchaRequest = ObjectGen.ComplexImageTask.CreateRecognitionComplexImageTask();
var expectedResult = ObjectGen.ComplexImageTask.CreateDynamicComplexImageTaskSolutionWithGridAnswer();

var expectedRequests = new List<(RequestType Type, string ExpectedRequest)>
{
(
Type: RequestType.CreateTask,
ExpectedRequest: JsonConvert.SerializeObject(new
{ clientKey = clientKey, task = captchaRequest, softId = 53 })
),
(
Type: RequestType.GetTaskResult,
ExpectedRequest: JsonConvert.SerializeObject(new { clientKey = clientKey, taskId = taskId })
),
};

var captchaResults = new List<object>
{
new { taskId = taskId, errorId = 0, errorCode = (string)null! },
new
{
status = "ready",
solution = new
{
answer = expectedResult.Solution.Answer.GridAnswer,
metadata = new { AnswerType = "Grid" }
},
errorId = 0,
errorCode = (string)null!
}
};

var sut = new Sut(clientKey);
sut.SetupHttpServer(captchaResults);

var actual = await sut.SolveAsync(captchaRequest);

sut.GetActualRequests().Should().BeEquivalentTo(expectedRequests);
actual.Should().BeEquivalentTo(expectedResult);
}

[Test]
public async Task RecognitionComplexImageTaskWithNumericAnswer_ShouldSolve()
{
var clientKey = Gen.RandomString();
var taskId = Gen.RandomInt();

var captchaRequest = ObjectGen.ComplexImageTask.CreateRecognitionComplexImageTask();
var expectedResult = ObjectGen.ComplexImageTask.CreateDynamicComplexImageTaskSolutionWithNumericAnswer();

var expectedRequests = new List<(RequestType Type, string ExpectedRequest)>
{
(
Type: RequestType.CreateTask,
ExpectedRequest: JsonConvert.SerializeObject(new
{ clientKey = clientKey, task = captchaRequest, softId = 53 })
),
(
Type: RequestType.GetTaskResult,
ExpectedRequest: JsonConvert.SerializeObject(new { clientKey = clientKey, taskId = taskId })
),
};

var captchaResults = new List<object>
{
new { taskId = taskId, errorId = 0, errorCode = (string)null! },
new
{
status = "ready",
solution = new
{
answer = expectedResult.Solution.Answer.NumericAnswer,
metadata = new { AnswerType = "NumericArray" }
},
errorId = 0,
errorCode = (string)null!
}
};

var sut = new Sut(clientKey);
sut.SetupHttpServer(captchaResults);

var actual = await sut.SolveAsync(captchaRequest);

sut.GetActualRequests().Should().BeEquivalentTo(expectedRequests);
actual.Should().BeEquivalentTo(expectedResult);
}

[Test]
public async Task RecaptchaV2_IncorrectWebsiteUrl_ShouldThrowValidationException()
{
Expand Down Expand Up @@ -636,7 +824,7 @@
}

[Test]
public async Task RecaptchaV2_IncorrectProxyPort_ShouldThrowArgumentException()

Check warning on line 827 in CapMonsterCloud.Client.IntegrationTests/IntegrationTests.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 827 in CapMonsterCloud.Client.IntegrationTests/IntegrationTests.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
Action actual = () => ObjectGen.RecaptchaV2.CreateTask(
proxyPort: Gen.RandomInt(65535));
Expand Down
76 changes: 75 additions & 1 deletion CapMonsterCloud.Client.IntegrationTests/ObjectGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,24 @@ public static FunCaptchaComplexImageTaskRequest CreateFunCaptchaComplexImageTask
};
}

public static CaptchaResult<GridComplexImageTaskResponse> CreateSolution()

public static RecognitionComplexImageTaskRequest CreateRecognitionComplexImageTask()
{
return new RecognitionComplexImageTaskRequest
{
WebsiteUrl = Gen.RandomUri().ToString(),
Metadata = new RecognitionComplexImageTaskRequest.RecognitionMetadata
{
Task = Gen.RandomString(),
TaskArgument = Gen.RandomString()
},
ImageUrls = Gen.ListOfValues(Gen.RandomUri().ToString),
ImagesBase64 = Gen.ListOfValues(Gen.RandomString),
UserAgent = Gen.UserAgent()
};
}

public static CaptchaResult<GridComplexImageTaskResponse> CreateGridComplexImageTaskSolution()
{
return new CaptchaResult<GridComplexImageTaskResponse>
{
Expand All @@ -322,6 +339,32 @@ public static CaptchaResult<GridComplexImageTaskResponse> CreateSolution()
}
};
}

public static CaptchaResult<DynamicComplexImageTaskResponse> CreateDynamicComplexImageTaskSolutionWithGridAnswer()
{
return new CaptchaResult<DynamicComplexImageTaskResponse>
{
Error = null,
Solution = new DynamicComplexImageTaskResponse
{
Answer = new RecognitionAnswer{ GridAnswer = Gen.ArrayOfValues(Gen.RandomBool) },
Metadata = new DynamicComplexImageTaskResponse.RecognitionMetadata { AnswerType = "Grid" }
}
};
}

public static CaptchaResult<DynamicComplexImageTaskResponse> CreateDynamicComplexImageTaskSolutionWithNumericAnswer()
{
return new CaptchaResult<DynamicComplexImageTaskResponse>
{
Error = null,
Solution = new DynamicComplexImageTaskResponse
{
Answer = new RecognitionAnswer { NumericAnswer = Gen.ArrayOfValues(Gen.RandomDecimal) },
Metadata = new DynamicComplexImageTaskResponse.RecognitionMetadata { AnswerType = "NumericArray" }
}
};
}
}

public static class CustomTask
Expand Down Expand Up @@ -409,6 +452,37 @@ public static CaptchaResult<CustomTaskResponse> CreateBasiliskSolution()
}
};
}

public static ImpervaCustomTaskRequest CreateImpervaTask()
{
return new ImpervaCustomTaskRequest(Gen.RandomString(), Gen.RandomString(), Gen.RandomString())
{
WebsiteUrl = Gen.RandomUri().ToString(),
UserAgent = Gen.UserAgent(),
Proxy = new ProxyContainer(Gen.RandomString(), Gen.RandomInt(0, 65535), Gen.RandomEnum<ProxyType>(), Gen.RandomString(), Gen.RandomString())
};
}

public static CaptchaResult<CustomTaskResponse> CreateImpervaSolution()
{
return new CaptchaResult<CustomTaskResponse>
{
Error = null,
Solution = new CustomTaskResponse
{
Domains = new Dictionary<string, CustomTaskResponse.DomainInfo>
{
{
Gen.RandomString(),
new CustomTaskResponse.DomainInfo()
{
Cookies = new Dictionary<string, string> { { Gen.RandomString(), Gen.RandomString() } },
}
}
}
}
};
}
}

public static class AmazonWaf
Expand Down
10 changes: 8 additions & 2 deletions CapMonsterCloud.Client.IntegrationTests/Sut.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ public async Task<CaptchaResult<TurnstileResponse>> SolveAsync (
public async Task<CaptchaResult<GridComplexImageTaskResponse>> SolveAsync (
RecaptchaComplexImageTaskRequest request) => await _cloudClient.SolveAsync<GridComplexImageTaskResponse>(request);

public async Task<CaptchaResult<GridComplexImageTaskResponse>> SolveAsync (
HCaptchaComplexImageTaskRequest request) => await _cloudClient.SolveAsync<GridComplexImageTaskResponse>(request);
public async Task<CaptchaResult<DynamicComplexImageTaskResponse>> SolveAsync (
HCaptchaComplexImageTaskRequest request) => await _cloudClient.SolveAsync<DynamicComplexImageTaskResponse>(request);

public async Task<CaptchaResult<GridComplexImageTaskResponse>> SolveAsync (
FunCaptchaComplexImageTaskRequest request) => await _cloudClient.SolveAsync<GridComplexImageTaskResponse>(request);
Expand All @@ -92,6 +92,12 @@ public async Task<CaptchaResult<CustomTaskResponse>> SolveAsync(
public async Task<CaptchaResult<BinanceTaskResponse>> SolveAsync(
BinanceTaskRequest request) => await _cloudClient.SolveAsync<BinanceTaskResponse>(request);

public async Task<CaptchaResult<CustomTaskResponse>> SolveAsync(
ImpervaCustomTaskRequest request) => await _cloudClient.SolveAsync<CustomTaskResponse>(request);

public async Task<CaptchaResult<DynamicComplexImageTaskResponse>> SolveAsync(
RecognitionComplexImageTaskRequest request) => await _cloudClient.SolveAsync(request);

public async Task<decimal> GetBalanceAsync()
{
return await _cloudClient.GetBalanceAsync();
Expand Down
Loading
Loading