public async Task StartRecognizeContentSendsUserSpecifiedContentType() { var mockResponse = new MockResponse(202); mockResponse.AddHeader(new HttpHeader(Constants.OperationLocationHeader, "host/layout/analyzeResults/00000000000000000000000000000000")); var mockTransport = new MockTransport(new[] { mockResponse, mockResponse }); var options = new FormRecognizerClientOptions() { Transport = mockTransport }; var client = CreateInstrumentedClient(options); using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.InvoiceLeTiff); var recognizeOptions = new RecognizeContentOptions { ContentType = FormContentType.Jpeg }; await client.StartRecognizeContentAsync(stream, recognizeOptions); var request = mockTransport.Requests.Single(); Assert.True(request.Headers.TryGetValue("Content-Type", out var contentType)); Assert.AreEqual("image/jpeg", contentType); }
public async Task StartRecognizeContentWithReadingOrder() { var client = CreateFormRecognizerClient(); var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.Form1); RecognizeContentOperation basicOrderOperation, naturalOrderOperation; basicOrderOperation = await client.StartRecognizeContentFromUriAsync(uri, new RecognizeContentOptions() { ReadingOrder = FormReadingOrder.Basic }); naturalOrderOperation = await client.StartRecognizeContentFromUriAsync(uri, new RecognizeContentOptions() { ReadingOrder = FormReadingOrder.Natural }); await basicOrderOperation.WaitForCompletionAsync(); Assert.IsTrue(basicOrderOperation.HasValue); await naturalOrderOperation.WaitForCompletionAsync(); Assert.IsTrue(naturalOrderOperation.HasValue); var basicOrderFormPage = basicOrderOperation.Value.Single(); var naturalOrderFormPage = naturalOrderOperation.Value.Single(); ValidateFormPage(basicOrderFormPage, includeFieldElements: true, expectedPageNumber: 1); ValidateFormPage(naturalOrderFormPage, includeFieldElements: true, expectedPageNumber: 1); var basicOrderLines = basicOrderFormPage.Lines.Select(f => f.Text); var naturalOrderLines = naturalOrderFormPage.Lines.Select(f => f.Text); CollectionAssert.AreEquivalent(basicOrderLines, naturalOrderLines); CollectionAssert.AreNotEqual(basicOrderLines, naturalOrderLines); }
public async Task StartRecognizeCustomFormsWithoutLabelsCanParseMultipageFormWithBlankPage(bool useStream) { var client = CreateFormRecognizerClient(); var options = new RecognizeCustomFormsOptions() { IncludeFieldElements = true }; RecognizeCustomFormsOperation operation; await using var trainedModel = await CreateDisposableTrainedModelAsync(useTrainingLabels : false); if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.InvoiceMultipageBlank); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeCustomFormsAsync(trainedModel.ModelId, stream, options); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.InvoiceMultipageBlank); operation = await client.StartRecognizeCustomFormsFromUriAsync(trainedModel.ModelId, uri, options); } RecognizedFormCollection recognizedForms = await operation.WaitForCompletionAsync(); Assert.AreEqual(3, recognizedForms.Count); for (int formIndex = 0; formIndex < recognizedForms.Count; formIndex++) { var recognizedForm = recognizedForms[formIndex]; var expectedPageNumber = formIndex + 1; ValidateModelWithNoLabelsForm( recognizedForm, trainedModel.ModelId, includeFieldElements: true, expectedFirstPageNumber: expectedPageNumber, expectedLastPageNumber: expectedPageNumber); // Basic sanity test to make sure pages are ordered correctly. if (formIndex == 0 || formIndex == 2) { var expectedValueData = formIndex == 0 ? "300.00" : "3000.00"; FormField fieldInPage = recognizedForm.Fields.Values.Where(field => field.LabelData.Text.Contains("Subtotal:")).FirstOrDefault(); Assert.IsNotNull(fieldInPage); Assert.IsNotNull(fieldInPage.ValueData); Assert.AreEqual(expectedValueData, fieldInPage.ValueData.Text); } } var blankForm = recognizedForms[1]; Assert.AreEqual(0, blankForm.Fields.Count); var blankPage = blankForm.Pages.Single(); Assert.AreEqual(0, blankPage.Lines.Count); Assert.AreEqual(0, blankPage.Tables.Count); }
public async Task StartRecognizeContentPopulatesFormPage(bool useStream) { var client = CreateInstrumentedFormRecognizerClient(); RecognizeContentOperation operation; if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.InvoicePdf); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeContentAsync(stream); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.InvoicePdf); operation = await client.StartRecognizeContentFromUriAsync(uri); } await operation.WaitForCompletionAsync(); Assert.IsTrue(operation.HasValue); var formPage = operation.Value.Single(); // The expected values are based on the values returned by the service, and not the actual // values present in the form. We are not testing the service here, but the SDK. Assert.AreEqual(LengthUnit.Inch, formPage.Unit); Assert.AreEqual(8.5, formPage.Width); Assert.AreEqual(11, formPage.Height); Assert.AreEqual(0, formPage.TextAngle); Assert.AreEqual(18, formPage.Lines.Count); var lines = formPage.Lines.ToList(); for (var lineIndex = 0; lineIndex < lines.Count; lineIndex++) { var line = lines[lineIndex]; Assert.NotNull(line.Text, $"Text should not be null in line {lineIndex}. "); Assert.AreEqual(4, line.BoundingBox.Points.Count(), $"There should be exactly 4 points in the bounding box in line {lineIndex}."); Assert.Greater(line.Words.Count, 0, $"There should be at least one word in line {lineIndex}."); foreach (var item in line.Words) { Assert.GreaterOrEqual(item.Confidence, 0); } } var table = formPage.Tables.Single(); Assert.AreEqual(2, table.RowCount); Assert.AreEqual(6, table.ColumnCount); var cells = table.Cells.ToList(); Assert.AreEqual(10, cells.Count); var expectedText = new string[2, 6] { { "Invoice Number", "Invoice Date", "Invoice Due Date", "Charges", "", "VAT ID" }, { "34278587", "6/18/2017", "6/24/2017", "$56,651.49", "", "PT" } }; foreach (var cell in cells) { Assert.GreaterOrEqual(cell.RowIndex, 0, $"Cell with text {cell.Text} should have row index greater than or equal to zero."); Assert.Less(cell.RowIndex, table.RowCount, $"Cell with text {cell.Text} should have row index less than {table.RowCount}."); Assert.GreaterOrEqual(cell.ColumnIndex, 0, $"Cell with text {cell.Text} should have column index greater than or equal to zero."); Assert.Less(cell.ColumnIndex, table.ColumnCount, $"Cell with text {cell.Text} should have column index less than {table.ColumnCount}."); // There's a single cell in the table (row = 1, column = 3) that has a column span of 2. var expectedColumnSpan = (cell.RowIndex == 1 && cell.ColumnIndex == 3) ? 2 : 1; Assert.AreEqual(1, cell.RowSpan, $"Cell with text {cell.Text} should have a row span of 1."); Assert.AreEqual(expectedColumnSpan, cell.ColumnSpan, $"Cell with text {cell.Text} should have a column span of {expectedColumnSpan}."); Assert.AreEqual(expectedText[cell.RowIndex, cell.ColumnIndex], cell.Text); Assert.IsFalse(cell.IsFooter, $"Cell with text {cell.Text} should not have been classified as footer."); Assert.IsFalse(cell.IsHeader, $"Cell with text {cell.Text} should not have been classified as header."); Assert.GreaterOrEqual(cell.Confidence, 0, $"Cell with text {cell.Text} should have confidence greater or equal to zero."); Assert.LessOrEqual(cell.RowIndex, 1, $"Cell with text {cell.Text} should have a row index less than or equal to one."); Assert.Greater(cell.TextContent.Count, 0, $"Cell with text {cell.Text} should have text content."); } }
public async Task StartRecognizeReceiptsPopulatesExtractedReceipt(bool useStream) { var client = CreateInstrumentedFormRecognizerClient(); RecognizeReceiptsOperation operation; if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.ReceiptJpg); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeReceiptsAsync(stream); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.ReceiptJpg); operation = await client.StartRecognizeReceiptsFromUriAsync(uri, default); } await operation.WaitForCompletionAsync(); Assert.IsTrue(operation.HasValue); var receipt = operation.Value.Single().AsUSReceipt(); // The expected values are based on the values returned by the service, and not the actual // values present in the receipt. We are not testing the service here, but the SDK. Assert.AreEqual(USReceiptType.Itemized, receipt.ReceiptType); Assert.That(receipt.ReceiptTypeConfidence, Is.EqualTo(0.66).Within(0.01)); Assert.AreEqual(1, receipt.RecognizedForm.PageRange.FirstPageNumber); Assert.AreEqual(1, receipt.RecognizedForm.PageRange.LastPageNumber); Assert.AreEqual("Contoso Contoso", (string)receipt.MerchantName); Assert.AreEqual("123 Main Street Redmond, WA 98052", (string)receipt.MerchantAddress); Assert.AreEqual("123-456-7890", (string)receipt.MerchantPhoneNumber.ValueText); Assert.IsNotNull(receipt.TransactionDate); Assert.IsNotNull(receipt.TransactionTime); var date = receipt.TransactionDate.Value; var time = receipt.TransactionTime.Value; Assert.AreEqual(10, date.Day); Assert.AreEqual(6, date.Month); Assert.AreEqual(2019, date.Year); Assert.AreEqual(13, time.Hours); Assert.AreEqual(59, time.Minutes); Assert.AreEqual(0, time.Seconds); var expectedItems = new List <(int?Quantity, string Name, float?Price, float?TotalPrice)>() { (null, "8GB RAM (Black)", null, 999.00f), (1, "SurfacePen", null, 99.99f) }; // Include a bit of tolerance when comparing float types. Assert.AreEqual(expectedItems.Count, receipt.Items.Count); for (var itemIndex = 0; itemIndex < receipt.Items.Count; itemIndex++) { var receiptItem = receipt.Items[itemIndex]; var expectedItem = expectedItems[itemIndex]; Assert.AreEqual(expectedItem.Quantity, receiptItem.Quantity == null? null : (float?)receiptItem.Quantity, $"{receiptItem.Quantity} mismatch in item with index {itemIndex}."); Assert.AreEqual(expectedItem.Name, (string)receiptItem.Name, $"{receiptItem.Name} mismatch in item with index {itemIndex}."); Assert.That(receiptItem.Price == null? null : (float?)receiptItem.Price, Is.EqualTo(expectedItem.Price).Within(0.0001), $"{receiptItem.Price} mismatch in item with index {itemIndex}."); Assert.That(receiptItem.TotalPrice == null? null: (float?)receiptItem.TotalPrice, Is.EqualTo(expectedItem.TotalPrice).Within(0.0001), $"{receiptItem.TotalPrice} mismatch in item with index {itemIndex}."); } Assert.That((float?)receipt.Subtotal, Is.EqualTo(1098.99).Within(0.0001)); Assert.That((float?)receipt.Tax, Is.EqualTo(104.40).Within(0.0001)); Assert.IsNull(receipt.Tip); Assert.That((float?)receipt.Total, Is.EqualTo(1203.39).Within(0.0001)); }
public async Task StartRecognizeContentPopulatesFormPageJpg(bool useStream) { var client = CreateFormRecognizerClient(); RecognizeContentOperation operation; if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.Form1); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeContentAsync(stream); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.Form1); operation = await client.StartRecognizeContentFromUriAsync(uri); } await operation.WaitForCompletionAsync(); Assert.IsTrue(operation.HasValue); var formPage = operation.Value.Single(); // The expected values are based on the values returned by the service, and not the actual // values present in the form. We are not testing the service here, but the SDK. Assert.AreEqual(LengthUnit.Pixel, formPage.Unit); Assert.AreEqual(1700, formPage.Width); Assert.AreEqual(2200, formPage.Height); Assert.AreEqual(0, formPage.TextAngle); Assert.AreEqual(54, formPage.Lines.Count); var lines = formPage.Lines.ToList(); for (var lineIndex = 0; lineIndex < lines.Count; lineIndex++) { var line = lines[lineIndex]; Assert.NotNull(line.Text, $"Text should not be null in line {lineIndex}."); Assert.AreEqual(4, line.BoundingBox.Points.Count(), $"There should be exactly 4 points in the bounding box in line {lineIndex}."); Assert.Greater(line.Words.Count, 0, $"There should be at least one word in line {lineIndex}."); foreach (var item in line.Words) { Assert.GreaterOrEqual(item.Confidence, 0); } Assert.IsNotNull(line.Appearance); Assert.IsNotNull(line.Appearance.Style); Assert.Greater(line.Appearance.Style.Confidence, 0f); if (lineIndex == 45) { Assert.AreEqual(TextStyleName.Handwriting, line.Appearance.Style.Name); } else { Assert.AreEqual(TextStyleName.Other, line.Appearance.Style.Name); } } Assert.AreEqual(2, formPage.Tables.Count); var sampleTable = formPage.Tables[1]; Assert.AreEqual(4, sampleTable.RowCount); Assert.AreEqual(2, sampleTable.ColumnCount); Assert.AreEqual(4, sampleTable.BoundingBox.Points.Count(), $"There should be exactly 4 points in the table bounding box."); var cells = sampleTable.Cells.ToList(); Assert.AreEqual(8, cells.Count); var expectedText = new string[4, 2] { { "SUBTOTAL", "$140.00" }, { "TAX", "$4.00" }, { "", "" }, { "TOTAL", "$144.00" } }; for (int i = 0; i < cells.Count; i++) { Assert.GreaterOrEqual(cells[i].RowIndex, 0, $"Cell with text {cells[i].Text} should have row index greater than or equal to zero."); Assert.Less(cells[i].RowIndex, sampleTable.RowCount, $"Cell with text {cells[i].Text} should have row index less than {sampleTable.RowCount}."); Assert.GreaterOrEqual(cells[i].ColumnIndex, 0, $"Cell with text {cells[i].Text} should have column index greater than or equal to zero."); Assert.Less(cells[i].ColumnIndex, sampleTable.ColumnCount, $"Cell with text {cells[i].Text} should have column index less than {sampleTable.ColumnCount}."); Assert.AreEqual(1, cells[i].RowSpan, $"Cell with text {cells[i].Text} should have a row span of 1."); Assert.AreEqual(1, cells[i].ColumnSpan, $"Cell with text {cells[i].Text} should have a column span of 1."); Assert.AreEqual(expectedText[cells[i].RowIndex, cells[i].ColumnIndex], cells[i].Text); Assert.IsFalse(cells[i].IsFooter, $"Cell with text {cells[i].Text} should not have been classified as footer."); Assert.IsFalse(cells[i].IsHeader, $"Cell with text {cells[i].Text} should not have been classified as header."); Assert.GreaterOrEqual(cells[i].Confidence, 0, $"Cell with text {cells[i].Text} should have confidence greater or equal to zero."); // Empty row if (cells[i].RowIndex != 2) { Assert.Greater(cells[i].FieldElements.Count, 0, $"Cell with text {cells[i].Text} should have at least one field element."); } else { Assert.AreEqual(0, cells[i].FieldElements.Count); } } }
public async Task StartRecognizeReceiptsPopulatesExtractedReceiptJpg(bool useStream) { var client = CreateFormRecognizerClient(); RecognizeReceiptsOperation operation; if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.ReceiptJpg); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeReceiptsAsync(stream); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.ReceiptJpg); operation = await client.StartRecognizeReceiptsFromUriAsync(uri, default); } await operation.WaitForCompletionAsync(); Assert.IsTrue(operation.HasValue); var form = operation.Value.Single(); Assert.NotNull(form); ValidatePrebuiltForm( form, includeFieldElements: true, expectedFirstPageNumber: 1, expectedLastPageNumber: 1); // The expected values are based on the values returned by the service, and not the actual // values present in the receipt. We are not testing the service here, but the SDK. Assert.AreEqual("prebuilt:receipt", form.FormType); Assert.AreEqual(1, form.PageRange.FirstPageNumber); Assert.AreEqual(1, form.PageRange.LastPageNumber); Assert.NotNull(form.Fields); Assert.True(form.Fields.ContainsKey("ReceiptType")); Assert.True(form.Fields.ContainsKey("MerchantAddress")); Assert.True(form.Fields.ContainsKey("MerchantName")); Assert.True(form.Fields.ContainsKey("MerchantPhoneNumber")); Assert.True(form.Fields.ContainsKey("TransactionDate")); Assert.True(form.Fields.ContainsKey("TransactionTime")); Assert.True(form.Fields.ContainsKey("Items")); Assert.True(form.Fields.ContainsKey("Subtotal")); Assert.True(form.Fields.ContainsKey("Tax")); Assert.True(form.Fields.ContainsKey("Total")); Assert.AreEqual("Itemized", form.Fields["ReceiptType"].Value.AsString()); Assert.AreEqual("Contoso", form.Fields["MerchantName"].Value.AsString()); Assert.AreEqual("123 Main Street Redmond, WA 98052", form.Fields["MerchantAddress"].Value.AsString()); Assert.AreEqual("123-456-7890", form.Fields["MerchantPhoneNumber"].ValueData.Text); var date = form.Fields["TransactionDate"].Value.AsDate(); var time = form.Fields["TransactionTime"].Value.AsTime(); Assert.AreEqual(10, date.Day); Assert.AreEqual(6, date.Month); Assert.AreEqual(2019, date.Year); Assert.AreEqual(13, time.Hours); Assert.AreEqual(59, time.Minutes); Assert.AreEqual(0, time.Seconds); var expectedItems = new List <(int?Quantity, string Name, float?Price, float?TotalPrice)>() { (1, "Surface Pro 6", null, 999.00f), (1, "SurfacePen", null, 99.99f) }; // Include a bit of tolerance when comparing float types. var items = form.Fields["Items"].Value.AsList(); Assert.AreEqual(expectedItems.Count, items.Count); for (var itemIndex = 0; itemIndex < items.Count; itemIndex++) { var receiptItemInfo = items[itemIndex].Value.AsDictionary(); receiptItemInfo.TryGetValue("Quantity", out var quantityField); receiptItemInfo.TryGetValue("Name", out var nameField); receiptItemInfo.TryGetValue("Price", out var priceField); receiptItemInfo.TryGetValue("TotalPrice", out var totalPriceField); var quantity = quantityField == null ? null : (float?)quantityField.Value.AsFloat(); var name = nameField == null ? null : nameField.Value.AsString(); var price = priceField == null ? null : (float?)priceField.Value.AsFloat(); var totalPrice = totalPriceField == null ? null : (float?)totalPriceField.Value.AsFloat(); var expectedItem = expectedItems[itemIndex]; Assert.AreEqual(expectedItem.Quantity, quantity, $"Quantity mismatch in item with index {itemIndex}."); Assert.AreEqual(expectedItem.Name, name, $"Name mismatch in item with index {itemIndex}."); Assert.That(price, Is.EqualTo(expectedItem.Price).Within(0.0001), $"Price mismatch in item with index {itemIndex}."); Assert.That(totalPrice, Is.EqualTo(expectedItem.TotalPrice).Within(0.0001), $"Total price mismatch in item with index {itemIndex}."); } Assert.That(form.Fields["Subtotal"].Value.AsFloat(), Is.EqualTo(1098.99).Within(0.0001)); Assert.That(form.Fields["Tax"].Value.AsFloat(), Is.EqualTo(104.40).Within(0.0001)); Assert.That(form.Fields["Total"].Value.AsFloat(), Is.EqualTo(1203.39).Within(0.0001)); }
public async Task StartRecognizeIdentityDocumentsPopulatesExtractedIdDocumentJpg(bool useStream) { var client = CreateFormRecognizerClient(); RecognizeIdentityDocumentsOperation operation; if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.DriverLicenseJpg); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeIdentityDocumentsAsync(stream); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.DriverLicenseJpg); operation = await client.StartRecognizeIdentityDocumentsFromUriAsync(uri); } await operation.WaitForCompletionAsync(); Assert.IsTrue(operation.HasValue); var form = operation.Value.Single(); Assert.NotNull(form); // The expected values are based on the values returned by the service, and not the actual // values present in the ID document. We are not testing the service here, but the SDK. Assert.AreEqual("prebuilt:idDocument:driverLicense", form.FormType); Assert.AreEqual(1, form.PageRange.FirstPageNumber); Assert.AreEqual(1, form.PageRange.LastPageNumber); Assert.NotNull(form.Fields); Assert.True(form.Fields.ContainsKey("Address")); Assert.True(form.Fields.ContainsKey("CountryRegion")); Assert.True(form.Fields.ContainsKey("DateOfBirth")); Assert.True(form.Fields.ContainsKey("DateOfExpiration")); Assert.True(form.Fields.ContainsKey("DocumentNumber")); Assert.True(form.Fields.ContainsKey("FirstName")); Assert.True(form.Fields.ContainsKey("LastName")); Assert.True(form.Fields.ContainsKey("Region")); Assert.True(form.Fields.ContainsKey("Sex")); Assert.AreEqual("123 STREET ADDRESS YOUR CITY WA 99999-1234", form.Fields["Address"].Value.AsString()); Assert.AreEqual("WDLABCD456DG", form.Fields["DocumentNumber"].Value.AsString()); Assert.AreEqual("LIAM R.", form.Fields["FirstName"].Value.AsString()); Assert.AreEqual("TALBOT", form.Fields["LastName"].Value.AsString()); Assert.AreEqual("Washington", form.Fields["Region"].Value.AsString()); Assert.AreEqual("M", form.Fields["Sex"].Value.AsString()); Assert.That(form.Fields["CountryRegion"].Value.AsCountryRegion(), Is.EqualTo("USA")); var dateOfBirth = form.Fields["DateOfBirth"].Value.AsDate(); Assert.AreEqual(6, dateOfBirth.Day); Assert.AreEqual(1, dateOfBirth.Month); Assert.AreEqual(1958, dateOfBirth.Year); var dateOfExpiration = form.Fields["DateOfExpiration"].Value.AsDate(); Assert.AreEqual(12, dateOfExpiration.Day); Assert.AreEqual(8, dateOfExpiration.Month); Assert.AreEqual(2020, dateOfExpiration.Year); }
public async Task StartRecognizeBusinessCardsPopulatesExtractedJpg(bool useStream) { var client = CreateFormRecognizerClient(); RecognizeBusinessCardsOperation operation; if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.BusinessCardJpg); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeBusinessCardsAsync(stream); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.BusinessCardJpg); operation = await client.StartRecognizeBusinessCardsFromUriAsync(uri); } await operation.WaitForCompletionAsync(); Assert.IsTrue(operation.HasValue); var form = operation.Value.Single(); Assert.NotNull(form); ValidatePrebuiltForm( form, includeFieldElements: true, expectedFirstPageNumber: 1, expectedLastPageNumber: 1); // The expected values are based on the values returned by the service, and not the actual // values present in the business card. We are not testing the service here, but the SDK. Assert.AreEqual("prebuilt:businesscard", form.FormType); Assert.AreEqual(1, form.PageRange.FirstPageNumber); Assert.AreEqual(1, form.PageRange.LastPageNumber); Assert.NotNull(form.Fields); Assert.True(form.Fields.ContainsKey("ContactNames")); Assert.True(form.Fields.ContainsKey("JobTitles")); Assert.True(form.Fields.ContainsKey("Departments")); Assert.True(form.Fields.ContainsKey("Emails")); Assert.True(form.Fields.ContainsKey("Websites")); Assert.True(form.Fields.ContainsKey("MobilePhones")); Assert.True(form.Fields.ContainsKey("WorkPhones")); Assert.True(form.Fields.ContainsKey("Faxes")); Assert.True(form.Fields.ContainsKey("Addresses")); Assert.True(form.Fields.ContainsKey("CompanyNames")); var contactNames = form.Fields["ContactNames"].Value.AsList(); Assert.AreEqual(1, contactNames.Count); Assert.AreEqual("Dr. Avery Smith", contactNames.FirstOrDefault().ValueData.Text); Assert.AreEqual(1, contactNames.FirstOrDefault().ValueData.PageNumber); var contactNamesDict = contactNames.FirstOrDefault().Value.AsDictionary(); Assert.True(contactNamesDict.ContainsKey("FirstName")); Assert.AreEqual("Avery", contactNamesDict["FirstName"].Value.AsString()); Assert.True(contactNamesDict.ContainsKey("LastName")); Assert.AreEqual("Smith", contactNamesDict["LastName"].Value.AsString()); var jobTitles = form.Fields["JobTitles"].Value.AsList(); Assert.AreEqual(1, jobTitles.Count); Assert.AreEqual("Senior Researcher", jobTitles.FirstOrDefault().Value.AsString()); var departments = form.Fields["Departments"].Value.AsList(); Assert.AreEqual(1, departments.Count); Assert.AreEqual("Cloud & Al Department", departments.FirstOrDefault().Value.AsString()); var emails = form.Fields["Emails"].Value.AsList(); Assert.AreEqual(1, emails.Count); Assert.AreEqual("*****@*****.**", emails.FirstOrDefault().Value.AsString()); var websites = form.Fields["Websites"].Value.AsList(); Assert.AreEqual(1, websites.Count); Assert.AreEqual("https://www.contoso.com/", websites.FirstOrDefault().Value.AsString()); // Update validation when https://github.com/Azure/azure-sdk-for-python/issues/14300 is fixed var mobilePhones = form.Fields["MobilePhones"].Value.AsList(); Assert.AreEqual(1, mobilePhones.Count); Assert.AreEqual(FieldValueType.PhoneNumber, mobilePhones.FirstOrDefault().Value.ValueType); var otherPhones = form.Fields["WorkPhones"].Value.AsList(); Assert.AreEqual(1, otherPhones.Count); Assert.AreEqual(FieldValueType.PhoneNumber, otherPhones.FirstOrDefault().Value.ValueType); var faxes = form.Fields["Faxes"].Value.AsList(); Assert.AreEqual(1, faxes.Count); Assert.AreEqual(FieldValueType.PhoneNumber, faxes.FirstOrDefault().Value.ValueType); var addresses = form.Fields["Addresses"].Value.AsList(); Assert.AreEqual(1, addresses.Count); Assert.AreEqual("2 Kingdom Street Paddington, London, W2 6BD", addresses.FirstOrDefault().Value.AsString()); var companyNames = form.Fields["CompanyNames"].Value.AsList(); Assert.AreEqual(1, companyNames.Count); Assert.AreEqual("Contoso", companyNames.FirstOrDefault().Value.AsString()); }
public async Task StartRecognizeBusinessCardsCanParseMultipageForm(bool useStream) { var client = CreateFormRecognizerClient(); var options = new RecognizeBusinessCardsOptions() { IncludeFieldElements = true }; RecognizeBusinessCardsOperation operation; if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.BusinessMultipage); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeBusinessCardsAsync(stream, options); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.BusinessMultipage); operation = await client.StartRecognizeBusinessCardsFromUriAsync(uri, options); } RecognizedFormCollection recognizedForms = await operation.WaitForCompletionAsync(); Assert.AreEqual(2, recognizedForms.Count); for (int formIndex = 0; formIndex < recognizedForms.Count; formIndex++) { var recognizedForm = recognizedForms[formIndex]; var expectedPageNumber = formIndex + 1; Assert.NotNull(recognizedForm); ValidatePrebuiltForm( recognizedForm, includeFieldElements: true, expectedFirstPageNumber: expectedPageNumber, expectedLastPageNumber: expectedPageNumber); // Basic sanity test to make sure pages are ordered correctly. Assert.IsTrue(recognizedForm.Fields.ContainsKey("Emails")); FormField sampleFields = recognizedForm.Fields["Emails"]; Assert.AreEqual(FieldValueType.List, sampleFields.Value.ValueType); var field = sampleFields.Value.AsList().Single(); if (formIndex == 0) { Assert.AreEqual("*****@*****.**", field.ValueData.Text); } else if (formIndex == 1) { Assert.AreEqual("*****@*****.**", field.ValueData.Text); } // Check for ContactNames.Page value Assert.IsTrue(recognizedForm.Fields.ContainsKey("ContactNames")); FormField contactNameField = recognizedForm.Fields["ContactNames"].Value.AsList().Single(); Assert.AreEqual(formIndex + 1, contactNameField.ValueData.PageNumber); } }
public async Task StartRecognizeInvoicesPopulatesExtractedJpg(bool useStream) { var client = CreateFormRecognizerClient(); RecognizeInvoicesOperation operation; if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.InvoiceJpg); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeInvoicesAsync(stream); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.InvoiceJpg); operation = await client.StartRecognizeInvoicesFromUriAsync(uri); } await operation.WaitForCompletionAsync(); Assert.IsTrue(operation.HasValue); var form = operation.Value.Single(); Assert.NotNull(form); // The expected values are based on the values returned by the service, and not the actual // values present in the invoice. We are not testing the service here, but the SDK. Assert.AreEqual("prebuilt:invoice", form.FormType); Assert.AreEqual(1, form.PageRange.FirstPageNumber); Assert.AreEqual(1, form.PageRange.LastPageNumber); Assert.NotNull(form.Fields); Assert.True(form.Fields.ContainsKey("AmountDue")); Assert.True(form.Fields.ContainsKey("BillingAddress")); Assert.True(form.Fields.ContainsKey("BillingAddressRecipient")); Assert.True(form.Fields.ContainsKey("CustomerAddress")); Assert.True(form.Fields.ContainsKey("CustomerAddressRecipient")); Assert.True(form.Fields.ContainsKey("CustomerId")); Assert.True(form.Fields.ContainsKey("CustomerName")); Assert.True(form.Fields.ContainsKey("DueDate")); Assert.True(form.Fields.ContainsKey("InvoiceDate")); Assert.True(form.Fields.ContainsKey("InvoiceId")); Assert.True(form.Fields.ContainsKey("InvoiceTotal")); Assert.True(form.Fields.ContainsKey("Items")); Assert.True(form.Fields.ContainsKey("PreviousUnpaidBalance")); Assert.True(form.Fields.ContainsKey("PurchaseOrder")); Assert.True(form.Fields.ContainsKey("RemittanceAddress")); Assert.True(form.Fields.ContainsKey("RemittanceAddressRecipient")); Assert.True(form.Fields.ContainsKey("ServiceAddress")); Assert.True(form.Fields.ContainsKey("ServiceAddressRecipient")); Assert.True(form.Fields.ContainsKey("ServiceEndDate")); Assert.True(form.Fields.ContainsKey("ServiceStartDate")); Assert.True(form.Fields.ContainsKey("ShippingAddress")); Assert.True(form.Fields.ContainsKey("ShippingAddressRecipient")); Assert.True(form.Fields.ContainsKey("SubTotal")); Assert.True(form.Fields.ContainsKey("TotalTax")); Assert.True(form.Fields.ContainsKey("VendorAddress")); Assert.True(form.Fields.ContainsKey("VendorAddressRecipient")); Assert.True(form.Fields.ContainsKey("VendorName")); Assert.That(form.Fields["AmountDue"].Value.AsFloat(), Is.EqualTo(610.00).Within(0.0001)); Assert.AreEqual("123 Bill St, Redmond WA, 98052", form.Fields["BillingAddress"].Value.AsString()); Assert.AreEqual("Microsoft Finance", form.Fields["BillingAddressRecipient"].Value.AsString()); Assert.AreEqual("123 Other St, Redmond WA, 98052", form.Fields["CustomerAddress"].Value.AsString()); Assert.AreEqual("Microsoft Corp", form.Fields["CustomerAddressRecipient"].Value.AsString()); Assert.AreEqual("CID-12345", form.Fields["CustomerId"].Value.AsString()); Assert.AreEqual("MICROSOFT CORPORATION", form.Fields["CustomerName"].Value.AsString()); var dueDate = form.Fields["DueDate"].Value.AsDate(); Assert.AreEqual(15, dueDate.Day); Assert.AreEqual(12, dueDate.Month); Assert.AreEqual(2019, dueDate.Year); var invoiceDate = form.Fields["InvoiceDate"].Value.AsDate(); Assert.AreEqual(15, invoiceDate.Day); Assert.AreEqual(11, invoiceDate.Month); Assert.AreEqual(2019, invoiceDate.Year); Assert.AreEqual("INV-100", form.Fields["InvoiceId"].Value.AsString()); Assert.That(form.Fields["InvoiceTotal"].Value.AsFloat(), Is.EqualTo(110.00).Within(0.0001)); Assert.That(form.Fields["PreviousUnpaidBalance"].Value.AsFloat(), Is.EqualTo(500.00).Within(0.0001)); Assert.AreEqual("PO-3333", form.Fields["PurchaseOrder"].Value.AsString()); Assert.AreEqual("123 Remit St New York, NY, 10001", form.Fields["RemittanceAddress"].Value.AsString()); Assert.AreEqual("Contoso Billing", form.Fields["RemittanceAddressRecipient"].Value.AsString()); Assert.AreEqual("123 Service St, Redmond WA, 98052", form.Fields["ServiceAddress"].Value.AsString()); Assert.AreEqual("Microsoft Services", form.Fields["ServiceAddressRecipient"].Value.AsString()); var serviceEndDate = form.Fields["ServiceEndDate"].Value.AsDate(); Assert.AreEqual(14, serviceEndDate.Day); Assert.AreEqual(11, serviceEndDate.Month); Assert.AreEqual(2019, serviceEndDate.Year); var serviceStartDate = form.Fields["ServiceStartDate"].Value.AsDate(); Assert.AreEqual(14, serviceStartDate.Day); Assert.AreEqual(10, serviceStartDate.Month); Assert.AreEqual(2019, serviceStartDate.Year); Assert.AreEqual("123 Ship St, Redmond WA, 98052", form.Fields["ShippingAddress"].Value.AsString()); Assert.AreEqual("Microsoft Delivery", form.Fields["ShippingAddressRecipient"].Value.AsString()); Assert.That(form.Fields["SubTotal"].Value.AsFloat(), Is.EqualTo(100.00).Within(0.0001)); Assert.That(form.Fields["TotalTax"].Value.AsFloat(), Is.EqualTo(10.00).Within(0.0001)); Assert.AreEqual("123 456th St New York, NY, 10001", form.Fields["VendorAddress"].Value.AsString()); Assert.AreEqual("Contoso Headquarters", form.Fields["VendorAddressRecipient"].Value.AsString()); Assert.AreEqual("CONTOSO LTD.", form.Fields["VendorName"].Value.AsString()); // TODO: add validation for Tax which currently don't have `valuenumber` properties. // Issue: https://github.com/Azure/azure-sdk-for-net/issues/20014 // TODO: add validation for Unit which currently is set as type `number` but should be `string`. // Issue: https://github.com/Azure/azure-sdk-for-net/issues/20015 var expectedItems = new List <(float?Amount, DateTime Date, string Description, string ProductCode, float?Quantity, float?UnitPrice)>() { (60f, DateTime.Parse("2021-03-04 00:00:00"), "Consulting Services", "A123", 2f, 30f), (30f, DateTime.Parse("2021-03-05 00:00:00"), "Document Fee", "B456", 3f, 10f), (10f, DateTime.Parse("2021-03-06 00:00:00"), "Printing Fee", "C789", 10f, 1f) }; // Include a bit of tolerance when comparing float types. var items = form.Fields["Items"].Value.AsList(); Assert.AreEqual(expectedItems.Count, items.Count); for (var itemIndex = 0; itemIndex < items.Count; itemIndex++) { var receiptItemInfo = items[itemIndex].Value.AsDictionary(); receiptItemInfo.TryGetValue("Amount", out var amountField); receiptItemInfo.TryGetValue("Date", out var dateField); receiptItemInfo.TryGetValue("Description", out var descriptionField); receiptItemInfo.TryGetValue("ProductCode", out var productCodeField); receiptItemInfo.TryGetValue("Quantity", out var quantityField); receiptItemInfo.TryGetValue("UnitPrice", out var unitPricefield); float? amount = amountField.Value.AsFloat(); string description = descriptionField.Value.AsString(); string productCode = productCodeField.Value.AsString(); float? quantity = quantityField?.Value.AsFloat(); float? unitPrice = unitPricefield.Value.AsFloat(); Assert.IsNotNull(dateField); DateTime date = dateField.Value.AsDate(); var expectedItem = expectedItems[itemIndex]; Assert.That(amount, Is.EqualTo(expectedItem.Amount).Within(0.0001), $"Amount mismatch in item with index {itemIndex}."); Assert.AreEqual(expectedItem.Date, date, $"Date mismatch in item with index {itemIndex}."); Assert.AreEqual(expectedItem.Description, description, $"Description mismatch in item with index {itemIndex}."); Assert.AreEqual(expectedItem.ProductCode, productCode, $"ProductCode mismatch in item with index {itemIndex}."); Assert.That(quantity, Is.EqualTo(expectedItem.Quantity).Within(0.0001), $"Quantity mismatch in item with index {itemIndex}."); Assert.That(unitPrice, Is.EqualTo(expectedItem.UnitPrice).Within(0.0001), $"UnitPrice price mismatch in item with index {itemIndex}."); } }
public async Task StartRecognizeInvoicesCanParseMultipageForm(bool useStream) { var client = CreateFormRecognizerClient(); var options = new RecognizeInvoicesOptions() { IncludeFieldElements = true }; RecognizeInvoicesOperation operation; if (useStream) { using var stream = FormRecognizerTestEnvironment.CreateStream(TestFile.InvoiceMultipage); using (Recording.DisableRequestBodyRecording()) { operation = await client.StartRecognizeInvoicesAsync(stream, options); } } else { var uri = FormRecognizerTestEnvironment.CreateUri(TestFile.InvoiceMultipage); operation = await client.StartRecognizeInvoicesFromUriAsync(uri, options); } RecognizedFormCollection recognizedForms = await operation.WaitForCompletionAsync(); var form = recognizedForms.Single(); Assert.NotNull(form); // The expected values are based on the values returned by the service, and not the actual // values present in the invoice. We are not testing the service here, but the SDK. Assert.AreEqual("prebuilt:invoice", form.FormType); Assert.AreEqual(1, form.PageRange.FirstPageNumber); Assert.AreEqual(2, form.PageRange.LastPageNumber); Assert.NotNull(form.Fields); Assert.True(form.Fields.ContainsKey("VendorName")); Assert.True(form.Fields.ContainsKey("RemittanceAddressRecipient")); Assert.True(form.Fields.ContainsKey("RemittanceAddress")); FormField vendorName = form.Fields["VendorName"]; Assert.AreEqual(2, vendorName.ValueData.PageNumber); Assert.AreEqual("Southridge Video", vendorName.Value.AsString()); FormField addressRecepient = form.Fields["RemittanceAddressRecipient"]; Assert.AreEqual(1, addressRecepient.ValueData.PageNumber); Assert.AreEqual("Contoso Ltd.", addressRecepient.Value.AsString()); FormField address = form.Fields["RemittanceAddress"]; Assert.AreEqual(1, address.ValueData.PageNumber); Assert.AreEqual("2345 Dogwood Lane Birch, Kansas 98123", address.Value.AsString()); ValidatePrebuiltForm( form, includeFieldElements: true, expectedFirstPageNumber: 1, expectedLastPageNumber: 2); }