Skip to content

Commit 64a7098

Browse files
author
Tomas Rutkauskas
committed
Refactor CLI argument handling and improve test coverage
Enhanced CLI argument parsing to validate inputs, infer formats, and handle dynamic properties more effectively. Refactored tests to use async Main calls, ensuring better alignment with updated argument handling logic. Added new tests for edge cases and additional format conversions to improve overall test coverage.
1 parent 0fb0970 commit 64a7098

File tree

2 files changed

+109
-57
lines changed

2 files changed

+109
-57
lines changed

ConvertApi.Cli.Test/DirectCallTests.cs

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,62 +13,110 @@ public void Setup()
1313
{
1414
Directory.Delete(TestOutputDir, true);
1515
}
16+
1617
Directory.CreateDirectory(TestOutputDir);
1718
}
1819

1920
[Test]
20-
public void TestConvertPdfToDocx()
21+
public async Task TestConvertPdfToDocx()
2122
{
2223
var outputFile = Path.Combine(TestOutputDir, "simple.docx");
2324
var inputFile = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "simple.pdf");
2425

25-
Run($"{ApiToken} {outputFile} {inputFile}", inputFile);
26+
await Program.Main([ApiToken, outputFile, inputFile]);
27+
28+
Assert.IsTrue(File.Exists(outputFile), "Output file was not created.");
29+
}
30+
31+
[Test]
32+
public async Task TestMergePdfs()
33+
{
34+
var outputFile = Path.Combine(TestOutputDir, "simple.pdf");
35+
var inputFile1 = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "simple.pdf");
36+
var inputFile2 = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "invoice.pdf");
37+
38+
await Program.Main([ApiToken, TestOutputDir, inputFile1, inputFile2, "pdf", "merge"]);
39+
2640
Assert.IsTrue(File.Exists(outputFile), "Output file was not created.");
2741
}
2842

2943
[Test]
30-
public void TestMergePdfs()
44+
public async Task TestMergeMutiplePdfs()
3145
{
3246
var outputFile = Path.Combine(TestOutputDir, "simple.pdf");
3347
var inputFile1 = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "simple.pdf");
3448
var inputFile2 = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "invoice.pdf");
35-
Run($"{ApiToken} {outputFile} {inputFile1} {inputFile2} pdf merge", $"{inputFile1}{Environment.NewLine}{inputFile2}{Environment.NewLine}");
49+
var inputFile3 = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "invoice.pdf");
50+
51+
await Program.Main([ApiToken, TestOutputDir, inputFile1, inputFile2, inputFile3, "pdf", "merge"]);
3652

3753
Assert.IsTrue(File.Exists(outputFile), "Output file was not created.");
3854
}
3955

4056
[Test]
41-
public void TestAddWatermarkToPdf()
57+
public async Task TestAddWatermarkToPdf()
4258
{
4359
var outputFile = Path.Combine(TestOutputDir, "watermark.pdf");
4460
var inputFile = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "simple.pdf");
45-
Run($"{ApiToken} {outputFile} {inputFile} pdf watermark Text=Confidential FileName=watermark", inputFile);
61+
62+
await Program.Main([ApiToken, TestOutputDir, inputFile, "pdf", "watermark", "Text=Confidential", "FileName=watermark"]);
63+
4664

4765
Assert.IsTrue(File.Exists(outputFile), "Output file was not created.");
4866
}
4967

5068
[Test]
51-
public void TestProtectPdfWithPassword()
69+
public async Task TestProtectPdfWithPassword()
5270
{
5371
var outputFile = Path.Combine(TestOutputDir, "protected.pdf");
5472
var inputFile = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "simple.pdf");
55-
Run($"{ApiToken} {outputFile} {inputFile} pdf protect UserPassword=1234 OwnerPassword=abcd FileName=protected", inputFile);
56-
73+
74+
await Program.Main([ApiToken, TestOutputDir, inputFile, "pdf", "protect", "UserPassword=1234", "OwnerPassword=abcd", "FileName=protected"]);
75+
5776
Assert.IsTrue(File.Exists(outputFile), "Output file was not created.");
5877
}
5978

60-
private void Run(string arguments, string inputFiles = "")
79+
[Test]
80+
public async Task TestPdfToPngWithResolution()
6181
{
62-
var originalIn = Console.In;
63-
try
64-
{
65-
Console.SetIn(new StringReader(inputFiles));
66-
Program.Main(arguments.Split()).GetAwaiter().GetResult();
67-
}
68-
finally
69-
{
70-
// Restore the original input
71-
Console.SetIn(originalIn);
72-
}
82+
var inputFile = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "simple.pdf");
83+
84+
await Program.Main([ApiToken, TestOutputDir, inputFile, "pdf", "png", "Resolution=300"]);
85+
86+
Assert.IsTrue(File.Exists(outputFolder), "Output file was not created.");
87+
}
88+
89+
[Test]
90+
public async Task TestPdfToExtractImages()
91+
{
92+
var inputFile = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "simple.pdf");
93+
94+
await Program.Main([ApiToken, TestOutputDir, inputFile, "pdf", "extract-images"]);
95+
96+
Assert.IsTrue(File.Exists(outputFolder), "Output file was not created.");
97+
}
98+
99+
[Test]
100+
public async Task TestPdfToExtractImagesError()
101+
{
102+
var outputFolder = Path.Combine(TestOutputDir, "watermark.pdf");
103+
var inputFile = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "simple.pdf");
104+
105+
await Program.Main([ApiToken, TestOutputDir, inputFile, "pdf", "extract-images"]);
106+
107+
Should fail
108+
Assert.IsTrue(File.Exists(outputFolder), "Output file was not created.");
109+
}
110+
111+
[Test]
112+
public async Task TestWebToPdf()
113+
{
114+
var outputFolder = Path.Combine(TestOutputDir, "watermark.pdf");
115+
var inputFile = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "test_files", "simple.pdf");
116+
117+
await Program.Main([ApiToken, TestOutputDir, "", "web", "pdf", "url=https://www.google.com"]);
118+
119+
120+
Assert.IsTrue(File.Exists(outputFolder), "Output file was not created.");
73121
}
74122
}

ConvertApi.Cli/Program.cs

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,40 +12,50 @@ public class Program
1212

1313
public static async Task Main(string[] args)
1414
{
15-
if (args.Length < 2 && Console.IsInputRedirected == false)
15+
if (args.Length < 3)
1616
{
1717
DisplayHelp();
1818
return;
1919
}
2020

21-
string apiToken = args.Length > 0 ? args[0] : null;
22-
string outputFile = args.Length > 1 ? args[1] : null;
23-
string[] inputFiles;
21+
string apiToken = args[0];
22+
string outputFile = args[1];
2423

25-
if (Console.IsInputRedirected)
26-
{
27-
Console.WriteLine("Reading input files from PIPE...");
28-
var pipeInput = new List<string>();
29-
string line;
30-
while ((line = Console.ReadLine()) != null)
31-
{
32-
pipeInput.Add(line);
33-
}
24+
// Extract input files, formats, and dynamic properties
25+
int inputFilesEndIndex = args.Length > 4 && !args[^2].Contains('=') && !args[^1].Contains('=')
26+
? args.Length - 2 // Exclude [from-format] and [to-format]
27+
: args.Length;
3428

35-
inputFiles = pipeInput.ToArray();
29+
string[] inputFiles = args.Skip(2).Take(inputFilesEndIndex - 2).ToArray();
30+
31+
// Validate input files
32+
if (inputFiles.Length == 0)
33+
{
34+
Console.WriteLine("Error: At least one input file is required.");
35+
return;
3636
}
37-
else
37+
38+
foreach (var file in inputFiles)
3839
{
39-
int inputFilesCount = args.Length - 4; // Exclude API token, output file, from-format, and to-format
40-
if (inputFilesCount < 1)
40+
if (!File.Exists(file))
4141
{
42-
Console.WriteLine("Error: At least one input file is required.");
42+
Console.WriteLine($"Error: Input file not found: {file}");
4343
return;
4444
}
45-
46-
inputFiles = args.Skip(2).Take(inputFilesCount).ToArray();
4745
}
4846

47+
string fromFormat = args.Length > inputFilesEndIndex
48+
? args[^2] // Second-to-last argument
49+
: Path.GetExtension(inputFiles[0]).Trim('.').ToLower(); // Infer from first input file
50+
51+
string toFormat = args.Length > inputFilesEndIndex + 1
52+
? args[^1] // Last argument
53+
: Path.GetExtension(outputFile).Trim('.').ToLower(); // Infer from output file
54+
55+
56+
// Second to last argument
57+
// Last argument
58+
4959
// Validate input files
5060
foreach (var file in inputFiles)
5161
{
@@ -56,9 +66,7 @@ public static async Task Main(string[] args)
5666
}
5767
}
5868

59-
string fromFormat = args[^2];
60-
string toFormat = args[^1];
61-
69+
// Extract dynamic properties
6270
var dynamicProperties = args.Skip(2 + inputFiles.Length).Where(arg => arg.Contains('=')).ToDictionary(
6371
arg => arg.Split('=')[0],
6472
arg => arg.Split('=')[1]
@@ -84,10 +92,10 @@ static void DisplayHelp()
8492
Console.WriteLine(" convertapi-cli.exe YOUR_API_TOKEN merged_output.pdf file1.pdf file2.pdf file3.pdf pdf merge");
8593
Console.WriteLine();
8694
Console.WriteLine(" Protect a PDF with a password:");
87-
Console.WriteLine(" convertapi-cli.exe YOUR_API_TOKEN protected_output.pdf input.pdf UserPassword=1234 OwnerPassword=abcd");
95+
Console.WriteLine(" convertapi-cli.exe YOUR_API_TOKEN protected_output.pdf input.pdf pdf protect UserPassword=1234 OwnerPassword=abcd FileName=protected");
8896
Console.WriteLine();
8997
Console.WriteLine(" Add a watermark to a PDF:");
90-
Console.WriteLine(" convertapi-cli.exe YOUR_API_TOKEN watermarked_output.pdf input.pdf WatermarkText=Confidential");
98+
Console.WriteLine(" convertapi-cli.exe YOUR_API_TOKEN watermarked_output.pdf input.pdf pdf watermark Text=Confidential FileName=watermark");
9199
Console.WriteLine();
92100
Console.WriteLine("Dynamic Properties:");
93101
Console.WriteLine(" Specify additional parameters using key=value pairs, such as UserPassword, OwnerPassword, or WatermarkText, depending on the API being used.");
@@ -121,10 +129,7 @@ static async Task ConvertFiles(string apiToken, string fromFormat, string toForm
121129
{
122130
form.Add(new StreamContent(File.OpenRead(inputFile))
123131
{
124-
Headers =
125-
{
126-
ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") { Name = $"files[{fileIndex}]", FileName = Path.GetFileName(inputFile) }
127-
}
132+
Headers = { ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") { Name = $"files[{fileIndex}]", FileName = Path.GetFileName(inputFile) } }
128133
});
129134
fileIndex++;
130135
}
@@ -150,8 +155,7 @@ static async Task ConvertFiles(string apiToken, string fromFormat, string toForm
150155

151156
while ((section = await multipartReader.ReadNextSectionAsync()) != null)
152157
{
153-
if (Microsoft.Net.Http.Headers.ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition) &&
154-
(contentDisposition.FileName != null || contentDisposition.FileNameStar.HasValue))
158+
if (Microsoft.Net.Http.Headers.ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition) && (contentDisposition.FileName != null || contentDisposition.FileNameStar.HasValue))
155159
{
156160
var fileName = contentDisposition.FileNameStar.HasValue ? contentDisposition.FileNameStar.Value : contentDisposition.FileName.Value.Trim('"');
157161
var filePath = Directory.Exists(outputPath) ? Path.Combine(outputPath, fileName) : Path.Combine(Path.GetDirectoryName(outputPath), fileName);
@@ -171,12 +175,12 @@ static async Task ConvertFiles(string apiToken, string fromFormat, string toForm
171175
var errorContent = await response.Content.ReadAsStringAsync();
172176
Console.WriteLine($"Error: {response.StatusCode}. Response message: {errorContent}");
173177
}
174-
}
175-
}
176-
177-
static string GetVersion()
178+
}
179+
}
180+
181+
static string GetVersion()
178182
{
179183
var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;
180184
return version ?? "unknown";
181185
}
182-
}
186+
}

0 commit comments

Comments
 (0)