Skip to content

Commit c7d2b14

Browse files
author
Tomas Rutkauskas
committed
Add ConvertAPI CLI implementation with testing suite
Introduce a CLI tool for file conversion using ConvertAPI, supporting PDF transformation, merging, watermarking, and password protection. Added a testing suite powered by NUnit to validate CLI functionality and ensure robustness. Include basic project structure, `.sln` file, dependencies, and a `.gitignore` for generated files.
1 parent fd37073 commit c7d2b14

File tree

8 files changed

+394
-0
lines changed

8 files changed

+394
-0
lines changed

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
### Example user template template
2+
### Example user template
3+
4+
# IntelliJ project files
5+
.idea
6+
*.iml
7+
out
8+
gen
9+
obj/
10+
bin/
11+
*.user
12+
test_output

ConvertApi.Cli.Test/CliTests.cs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
using System.Diagnostics;
2+
3+
namespace ConvertApi.Cli.Test;
4+
5+
[TestFixture]
6+
public class CliTests
7+
{
8+
private static readonly string SolutionDirectory = GetSolutionDirectory();
9+
private static readonly string CliExecutablePath = Path.Combine(SolutionDirectory, "ConvertApi.Cli", "bin", "Debug", "net8.0", "convertapi-cli.exe");
10+
private const string ApiToken = "your_api_token_here"; // Provide your API token
11+
private static readonly string TestOutputDir = Path.Combine(SolutionDirectory, "test_output");
12+
13+
[SetUp]
14+
public void Setup()
15+
{
16+
if (Directory.Exists(TestOutputDir))
17+
{
18+
Directory.Delete(TestOutputDir, true);
19+
}
20+
Directory.CreateDirectory(TestOutputDir);
21+
}
22+
23+
[Test]
24+
public void TestConvertPdfToDocx()
25+
{
26+
var outputFile = Path.Combine(TestOutputDir, "output.docx");
27+
var inputFile = "sample.pdf";
28+
var process = RunCli($"{ApiToken} {outputFile} {inputFile} pdf docx");
29+
30+
Assert.AreEqual(0, process.ExitCode, "CLI did not exit cleanly.");
31+
Assert.IsTrue(File.Exists(outputFile), "Output file was not created.");
32+
}
33+
34+
[Test]
35+
public void TestMergePdfs()
36+
{
37+
var outputFile = Path.Combine(TestOutputDir, "merged.pdf");
38+
var process = RunCli($"{ApiToken} {outputFile} file1.pdf file2.pdf pdf merge");
39+
40+
Assert.AreEqual(0, process.ExitCode, "CLI did not exit cleanly.");
41+
Assert.IsTrue(File.Exists(outputFile), "Output file was not created.");
42+
}
43+
44+
[Test]
45+
public void TestAddWatermarkToPdf()
46+
{
47+
var outputFile = Path.Combine(TestOutputDir, "watermarked.pdf");
48+
var process = RunCli($"{ApiToken} {outputFile} sample.pdf pdf pdf WatermarkText=Confidential");
49+
50+
Assert.AreEqual(0, process.ExitCode, "CLI did not exit cleanly.");
51+
Assert.IsTrue(File.Exists(outputFile), "Output file was not created.");
52+
}
53+
54+
[Test]
55+
public void TestProtectPdfWithPassword()
56+
{
57+
var outputFile = Path.Combine(TestOutputDir, "protected.pdf");
58+
var process = RunCli($"{ApiToken} {outputFile} sample.pdf pdf pdf UserPassword=1234 OwnerPassword=abcd");
59+
60+
Assert.AreEqual(0, process.ExitCode, "CLI did not exit cleanly.");
61+
Assert.IsTrue(File.Exists(outputFile), "Output file was not created.");
62+
}
63+
64+
private Process RunCli(string arguments)
65+
{
66+
if (!File.Exists(CliExecutablePath))
67+
{
68+
throw new FileNotFoundException($"CLI executable not found at {CliExecutablePath}");
69+
}
70+
71+
var process = new Process
72+
{
73+
StartInfo = new ProcessStartInfo
74+
{
75+
FileName = CliExecutablePath,
76+
Arguments = arguments,
77+
RedirectStandardOutput = true,
78+
RedirectStandardError = true,
79+
UseShellExecute = false,
80+
CreateNoWindow = true
81+
}
82+
};
83+
84+
process.Start();
85+
process.WaitForExit();
86+
87+
Console.WriteLine(process.StandardOutput.ReadToEnd());
88+
Console.WriteLine(process.StandardError.ReadToEnd());
89+
90+
return process;
91+
}
92+
93+
private static string GetSolutionDirectory()
94+
{
95+
var directory = Directory.GetCurrentDirectory();
96+
while (!string.IsNullOrEmpty(directory) && !File.Exists(Path.Combine(directory, "ConvertApi.Cli.sln")))
97+
{
98+
directory = Directory.GetParent(directory)?.FullName;
99+
}
100+
101+
if (string.IsNullOrEmpty(directory))
102+
{
103+
throw new DirectoryNotFoundException("Solution directory not found.");
104+
}
105+
106+
return directory;
107+
}
108+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Microsoft.Net.Http.Headers;
2+
3+
namespace ConvertApi.Cli.Test;
4+
5+
[TestFixture]
6+
public class ContentDispositionHeaderValueTests
7+
{
8+
[Test]
9+
public void TryParse_ValidContentDisposition_ReturnsTrueAndParsesContentDisposition()
10+
{
11+
// Arrange
12+
var validContentDisposition = "form-data; name=\"file\"; filename=\"example.txt\"";
13+
14+
// Act
15+
var parseResult = ContentDispositionHeaderValue.TryParse(validContentDisposition, out var contentDisposition);
16+
17+
// Assert
18+
Assert.IsTrue(parseResult, "Expected TryParse to return true for a valid content disposition string.");
19+
Assert.IsNotNull(contentDisposition, "Expected contentDisposition to be parsed successfully.");
20+
Assert.AreEqual("example.txt", contentDisposition.FileName.Value, "FileName should match the provided filename.");
21+
Assert.AreEqual("file", contentDisposition.Name.Value, "Name should match the provided name.");
22+
}
23+
24+
[Test]
25+
public void TryParse_ValidContentDisposition_ReturnsTrueAndParsesContentDispositionSize()
26+
{
27+
// Arrange
28+
var validContentDisposition = "attachment; filename*=utf-8''demo.pdf; size=180658";
29+
30+
// Act
31+
var parseResult = ContentDispositionHeaderValue.TryParse(validContentDisposition, out var contentDisposition);
32+
33+
// Assert
34+
Assert.IsTrue(parseResult, "Expected TryParse to return true for a valid content disposition string.");
35+
Assert.IsNotNull(contentDisposition, "Expected contentDisposition to be parsed successfully.");
36+
Assert.AreEqual("demo.pdf", contentDisposition.FileNameStar.Value, "FileName should match the provided filename.");
37+
}
38+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
<IsTestProject>true</IsTestProject>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
14+
<PackageReference Include="Microsoft.Net.Http.Headers" Version="8.0.11" />
15+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
16+
<PackageReference Include="NUnit" Version="3.14.0"/>
17+
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/>
18+
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<Using Include="NUnit.Framework"/>
23+
</ItemGroup>
24+
25+
</Project>

ConvertApi.Cli.sln

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConvertApi.Cli", "ConvertApi.Cli\ConvertApi.Cli.csproj", "{006B1430-754B-46E0-BF11-2B9A759E6611}"
4+
EndProject
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConvertApi.Cli.Test", "ConvertApi.Cli.Test\ConvertApi.Cli.Test.csproj", "{B14DD22A-6CF3-4515-BFCB-7A7FDE5FD036}"
6+
EndProject
7+
Global
8+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9+
Debug|Any CPU = Debug|Any CPU
10+
Release|Any CPU = Release|Any CPU
11+
EndGlobalSection
12+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
13+
{006B1430-754B-46E0-BF11-2B9A759E6611}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14+
{006B1430-754B-46E0-BF11-2B9A759E6611}.Debug|Any CPU.Build.0 = Debug|Any CPU
15+
{006B1430-754B-46E0-BF11-2B9A759E6611}.Release|Any CPU.ActiveCfg = Release|Any CPU
16+
{006B1430-754B-46E0-BF11-2B9A759E6611}.Release|Any CPU.Build.0 = Release|Any CPU
17+
{B14DD22A-6CF3-4515-BFCB-7A7FDE5FD036}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18+
{B14DD22A-6CF3-4515-BFCB-7A7FDE5FD036}.Debug|Any CPU.Build.0 = Debug|Any CPU
19+
{B14DD22A-6CF3-4515-BFCB-7A7FDE5FD036}.Release|Any CPU.ActiveCfg = Release|Any CPU
20+
{B14DD22A-6CF3-4515-BFCB-7A7FDE5FD036}.Release|Any CPU.Build.0 = Release|Any CPU
21+
EndGlobalSection
22+
EndGlobal
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net8.0</TargetFramework>
4+
<ImplicitUsings>enable</ImplicitUsings>
5+
<Nullable>enable</Nullable>
6+
<OutputType>Exe</OutputType>
7+
<PublishSingleFile>true</PublishSingleFile>
8+
<!--<SelfContained>true</SelfContained>-->
9+
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
10+
<!--<PublishTrimmed>true</PublishTrimmed>
11+
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
12+
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>-->
13+
<AssemblyName>convertapi-cli</AssemblyName>
14+
<RootNamespace>ConvertApi.Cli</RootNamespace>
15+
</PropertyGroup>
16+
17+
<ItemGroup>
18+
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.11" />
19+
</ItemGroup>
20+
21+
</Project>

0 commit comments

Comments
 (0)