<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mukarram Javid</title>
    <description>The latest articles on DEV Community by Mukarram Javid (@mukarramjavid).</description>
    <link>https://dev.to/mukarramjavid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F612771%2F78571ef6-d17f-42c3-8286-4ff317c9ca98.jpeg</url>
      <title>DEV Community: Mukarram Javid</title>
      <link>https://dev.to/mukarramjavid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mukarramjavid"/>
    <language>en</language>
    <item>
      <title>Automate Web Testing in C#: A Guide with PuppeteerSharp and SpecFlow</title>
      <dc:creator>Mukarram Javid</dc:creator>
      <pubDate>Sat, 09 Nov 2024 22:15:11 +0000</pubDate>
      <link>https://dev.to/mukarramjavid/automate-web-testing-in-c-a-guide-with-puppeteersharp-and-specflow-48</link>
      <guid>https://dev.to/mukarramjavid/automate-web-testing-in-c-a-guide-with-puppeteersharp-and-specflow-48</guid>
      <description>&lt;p&gt;Learn how to efficiently automate and test web applications in C# using PuppeteerSharp and SpecFlow for streamlined end-to-end testing.&lt;/p&gt;

&lt;p&gt;This article may be longer than expected, but I hope you enjoy it.&lt;/p&gt;

&lt;p&gt;We often need to automate tasks or test applications as developers or testers. In such cases, there is usually limited time for manual testing, making &lt;a href="https://www.puppeteersharp.com/" rel="noopener noreferrer"&gt;PuppeteerSharp&lt;/a&gt; an ideal tool for task automation.&lt;/p&gt;

&lt;p&gt;Before starting, we need to install two NuGet packages by running the following commands in the Package Manager Console window.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install-Package SpecFlow.NUnit
Install-Package PuppeteerSharp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have discussed Puppeteer in a previous blog you can read it by clicking &lt;a href="https://medium.com/@mukarramjavid/automate-browser-using-puppeteer-sharp-in-c-fa4269ba472d" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ll have a small discussion regarding &lt;a href="https://docs.specflow.org/projects/getting-started/en/latest/index.html#" rel="noopener noreferrer"&gt;SpecFlow&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SpecFlow is a .NET tool used to support Behavior-Driven Development (BDD) by enabling you to write tests in plain language that are easy to read and understand. SpecFlow allows developers and non-technical stakeholders to collaborate on defining application behavior in terms of scenarios written in Gherkin syntax (Given-When-Then format)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Key Features of SpecFlow&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gherkin Syntax: Write test scenarios in plain English, making them accessible to both technical and non-technical team members.
Integration with .NET: SpecFlow is designed specifically for the .NET ecosystem, enabling seamless integration with tools like NUnit, MSTest, and xUnit.&lt;/li&gt;
&lt;li&gt;Automated Tests: Scenarios written in SpecFlow can be automatically converted into executable test cases, which can be run to verify application behavior.&lt;/li&gt;
&lt;li&gt;BDD Workflow: Facilitates a BDD approach, where teams define requirements through examples, making tests serve as both documentation and a verification tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By combining SpecFlow with tools like PuppeteerSharp, you can create powerful, readable automation tests for web applications, streamlining both development and testing.&lt;/p&gt;

&lt;p&gt;Let’s dive into the coding part.&lt;/p&gt;

&lt;p&gt;In this article, I will use Visual Studio for development. we might need to install an &lt;a href="https://marketplace.visualstudio.com/items?itemName=TechTalkSpecFlowTeam.SpecFlowForVisualStudio2022" rel="noopener noreferrer"&gt;extension&lt;/a&gt; of SpecFlow in Visual Studio. You can either install it from VS 2022 or manually. It is totally upto you. I assume you have installed this extension.&lt;/p&gt;

&lt;p&gt;We create a NUnit project for this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F879jbfgj5w839b8yp889.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F879jbfgj5w839b8yp889.png" alt="nunit-project" width="745" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We do not need UnitTest1.cs file. So we can delete this. Our project will look like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwslcr5ffhqvs6byxphi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwslcr5ffhqvs6byxphi.png" alt="nunit-project-2" width="574" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now create some folders to manage our code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Utilities&lt;/strong&gt; (Helpers will be placed in the Utilities folder)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Features&lt;/strong&gt; (All Feature files will be stored in the Features folder)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steps&lt;/strong&gt; (Step definitions will be organized in the Steps folder)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62vp86la79sspafcd695.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62vp86la79sspafcd695.png" alt="TestScriptsView" width="574" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, we want to do GoogleSearch.&lt;/p&gt;

&lt;p&gt;Here will be our possible steps to do that search&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Google.com&lt;/li&gt;
&lt;li&gt;Write some text i.e PuppeteerSharp in the search bar&lt;/li&gt;
&lt;li&gt;Press Enter&lt;/li&gt;
&lt;li&gt;Match the search result with provided string.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To define steps we need .feature file. we will create the file in Features folder. “GoogleSearch.feature”. When we add New Item, we will see the SpecFlow section (if you installed SpecFlow extension) in left side of window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04v83eylafx3gjuhdv1r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04v83eylafx3gjuhdv1r.png" alt="feature-file-solution" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we click on this section. we will see related items of SpecFlow. We need Feature File for SpecFlow. Select it and named it and click on Add button&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15oo0yfxhmt0pxdvsxxj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15oo0yfxhmt0pxdvsxxj.png" alt="Image description" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After adding the feature file. Let’s breakdown of the contents of a Feature file:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Feature&lt;/strong&gt;&lt;br&gt;
The Feature keyword describes a high-level functionality or behavior of the application.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature: Google Search Functionality
  As a user
  I want to search for text on Google
  So that I can verify the search results match the expected output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In order to&lt;/strong&gt;: The goal or purpose of the feature.&lt;br&gt;
&lt;strong&gt;As a&lt;/strong&gt;: The role of the person interacting with the feature.&lt;br&gt;
&lt;strong&gt;I want to&lt;/strong&gt;: The actual action or behavior expected from the feature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Scenario&lt;/strong&gt;&lt;br&gt;
Each Scenario describes a test case with a clear purpose. In this case, the scenario is to search for the term “PuppeteerSharp” on Google and verify that the results contain the expected string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scenario: Search for PuppeteerSharp on Google
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Given, When, Then Steps&lt;/strong&gt;&lt;br&gt;
The Given, When, Then structure describes the flow of the scenario. Let’s map each of your steps to these terms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Given&lt;/strong&gt;: Describes the initial state (here, that the user is on Google’s homepage).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When&lt;/strong&gt;: Describes actions taken by the user (entering text and pressing Enter).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Then&lt;/strong&gt;: Describes the expected outcome (the search result should match the expected text).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how your scenario would look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Given I am on Google.com
  When I enter "PuppeteerSharp" in the search bar
  And I press Enter
  Then the search results should contain the text "PuppeteerSharp"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Full Feature File Example&lt;/strong&gt;&lt;br&gt;
Combining the elements above, here’s the full Feature file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# GoogleSearch.feature

Feature: Google Search Functionality
  As a user
  I want to search for text on Google
  So that I can verify the search results match the expected output

  Scenario: Search for PuppeteerSharp on Google
    Given I am on Google.com
    When I enter "PuppeteerSharp" in the search bar
    And I press Enter
    Then the search results should contain the text "PuppeteerSharp"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In SpecFlow, we will create methods for each step in a Step Definition file, which links the steps in your Feature file to the actual code that performs those actions. Each method corresponds to a specific step and uses attributes like [Given], [When], and [Then] to associate with the Gherkin steps.&lt;/p&gt;

&lt;p&gt;Here’s an example Step Definition file for your steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Binding]
 public class GoogleSearchSteps
 {
     [Given(@"I am on Google.com")]
     public async Task GivenIAmOnGoogleCom()
     {
     }

     [When(@"I enter ""(.*)"" in the search bar")]
     public async Task WhenIEnterTextInTheSearchBar(string searchText)
     {
     }

     [When(@"I press Enter")]
     public async Task WhenIPressEnter()
     {
     }

     [Then(@"the search results should contain the text ""(.*)""")]
     public async Task ThenTheSearchResultsShouldContainTheText(string expectedText)
     {
     }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To initialize the browser, we will create a file named BrowserHelper.cs in the Utilities folder and have the GoogleSearchSteps class inherit from it. In BrowserHelper.cs we initialize the browser using Puppeteer and GoogleSearchSteps inherit from it&lt;/p&gt;

&lt;p&gt;BrowserHelper will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  // BrowserHelper.cs

    public class BrowserHelper
    {
        public static IBrowser _browser;
        public static IPage _page;
        public async Task Init()
        {
            var revision = await new BrowserFetcher(SupportedBrowser.Chromium).DownloadAsync();

            _browser = await Puppeteer.LaunchAsync(new LaunchOptions()
            {
                Headless = false,
                ExecutablePath = revision.GetExecutablePath()
            });

            _page = await _browser.NewPageAsync();
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// GoogleSearchSteps

[Binding]
public class GoogleSearchSteps : BrowserHelper
{
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One more class we might need named Hook.&lt;/p&gt;

&lt;p&gt;In SpecFlow, the Hook class is used to execute specific code before or after certain events during test execution. Hooks provide a way to set up and tear down resources, prepare data, and perform cleanup tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. [Binding] Attribute&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Marks the Hooks class as a SpecFlow binding class, allowing SpecFlow to recognize and execute the hooks within this class.&lt;/li&gt;
&lt;li&gt;Ensures that the Hooks class is loaded and its hooks are applied to each test scenario.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Inheritance from BrowserHelper&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Hooks class inherits from BrowserHelper, suggesting that BrowserHelper contains methods or properties related to initializing or managing a browser instance.&lt;/li&gt;
&lt;li&gt;This inheritance likely provides access to browser-related functionality used for automated testing (such as launching or closing a browser).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. [BeforeScenario] Hook&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[BeforeScenario] is an attribute provided by SpecFlow that marks a method to be run before each test scenario begins.&lt;/li&gt;
&lt;li&gt;Purpose: This is often used to set up prerequisites for the test, such as initializing the browser, preparing test data, or configuring the environment.&lt;/li&gt;
&lt;li&gt;Implementation: In this example, FirstBeforeScenario():&lt;/li&gt;
&lt;li&gt;Calls the Init() method, which likely sets up a browser session.&lt;/li&gt;
&lt;li&gt;Init() is assumed to be a method from the BrowserHelper class.&lt;/li&gt;
&lt;li&gt;The method is asynchronous (async), allowing it to handle asynchronous browser setup processes if needed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[BeforeScenario]
public async Task FirstBeforeScenario()
{
    await Init(); // Initializes the browser session or other test prerequisites
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. [AfterScenario] Hook&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[AfterScenario] is another attribute provided by SpecFlow, but it is triggered after each test scenario has finished executing.&lt;/li&gt;
&lt;li&gt;Purpose: Commonly used to clean up resources or perform teardown operations after each test scenario, such as closing the browser, clearing test data, or resetting the environment.&lt;/li&gt;
&lt;li&gt;Implementation: In this example, AfterScenario():&lt;/li&gt;
&lt;li&gt;Calls _browser.CloseAsync(), which closes the browser session to free up resources.&lt;/li&gt;
&lt;li&gt;_browser is likely a browser instance that’s initialized in the - - ---- BrowserHelper class or Init() method.&lt;/li&gt;
&lt;li&gt;Again, the method is asynchronous, ensuring the browser shutdown operation completes before moving on.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[AfterScenario]
public async Task AfterScenario()
{
    await _browser.CloseAsync(); // Closes the browser session or cleans up resources
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hooks.cs will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Hooks.cs

[Binding]
public sealed class Hooks : BrowserHelper
{
    [BeforeScenario]
    public async Task FirstBeforeScenario()
    {
       await Init();
    }

    [AfterScenario]
    public async Task AfterScenario()
    {
       await _browser.CloseAsync();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s rebuild the project to resolve our dependencies. After building, open the Test Explorer to view our tests. The test window will then look like this:&lt;/p&gt;

&lt;p&gt;To see Test Explorer;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;View &amp;gt; Test Explorer&lt;/strong&gt; or we can use Short key &lt;strong&gt;CRTL + E, T&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiopkg3oqlpvwbwv1nykk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiopkg3oqlpvwbwv1nykk.png" alt="Image description" width="428" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run this test, right-click on the test SearchForPuppeteerSharpOnGoogle and select 'Run'. You will see the test running. The first time, it may take a bit longer because the compiler needs to download the Chromium browser. Once the browser is downloaded, the tests will begin to run.&lt;/p&gt;

&lt;p&gt;If the test has been successfully run, we will see a green icon indicating that the test passed successfully.&lt;/p&gt;

&lt;p&gt;You can find the source code from &lt;a href="https://github.com/mukarramjavid/TestScripts" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is done for now. Hopefully, you enjoyed it. Have a nice day. We will see next time and in a different blog.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>specflow</category>
      <category>testing</category>
      <category>puppeteer</category>
    </item>
    <item>
      <title>How to Create PDFs in React from JSON Data with jsPDF</title>
      <dc:creator>Mukarram Javid</dc:creator>
      <pubDate>Sat, 02 Nov 2024 22:34:27 +0000</pubDate>
      <link>https://dev.to/mukarramjavid/create-pdf-in-javascriptreact-using-json-data-1pj</link>
      <guid>https://dev.to/mukarramjavid/create-pdf-in-javascriptreact-using-json-data-1pj</guid>
      <description>&lt;p&gt;This article will show how to create PDF in JS/React from JSON data.&lt;/p&gt;

&lt;p&gt;As developers, we must integrate PDF generation within the application. So, in this article, we will discuss creating PDFs using jspdf.&lt;/p&gt;

&lt;p&gt;So, Let’s get started.&lt;/p&gt;

&lt;p&gt;We will use a React environment specifically for this article. I assume you’re familiar with JavaScript/React and have already set up the React environment&lt;/p&gt;

&lt;p&gt;Before diving in, we need some sample data to generate the PDF. We’ll create a method to generate this data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const generateUsers = (count) =&amp;gt; {
    const users = [];

    for (let i = 1; i &amp;lt;= count; i++) {
      const user = {
        id: i,
        firstName: `firstName_${i}`,
        lastName: `lastName_${i}`,
        email: `email_${i}@example.com`,
        address: [
          `Street ${i + 1}, Address Line 1`,
          `District ${(i % 7) + 1}, City_${i}`,
        ],
      };
      users.push(user);
    }
    return users;
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we need to install some npm packages jspdf and jspdf-autotable.&lt;/p&gt;

&lt;p&gt;jsPDF is responsible for creating PDFs, while jsPDF-AutoTable is used to display data in a table format within the PDF.&lt;/p&gt;

&lt;p&gt;You can use the following command to install both packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i jspdf-autotable jspdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we are going to develop a method to handle PDF creation. I’ll create a generic &lt;code&gt;generatePDF&lt;/code&gt; method, so you can use it anywhere you need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Function Definition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The function &lt;code&gt;generatePDF&lt;/code&gt; takes data as an argument, which is expected to be an array of objects (the JSON data to include in the PDF).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const generatePDF = (data) =&amp;gt; {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. PDF Document Setup&lt;/strong&gt;&lt;br&gt;
A new &lt;code&gt;jsPDF&lt;/code&gt; instance is created with the following options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"l" for landscape orientation.&lt;/li&gt;
&lt;li&gt;"pt" as the unit of measurement (points).&lt;/li&gt;
&lt;li&gt;"a3" as the paper size.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const doc = new jsPDF("l", "pt", "a3");

// if you want to use custom dimensions
// width,height

const doc = new jsPDF("l", "pt", [3000,1000]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;3. Adding Title to the PDF&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sets the font size to 16 points.&lt;/li&gt;
&lt;li&gt;Adds a centered title, "JSON Data PDF", at the top of the page (y-position of 30).
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;doc.setFontSize(16);
doc.text("JSON Data PDF", doc.internal.pageSize.getWidth() / 2, 30, {
    align: "center",
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;4. Extracting Table Headers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extracts the keys from the first object in &lt;code&gt;data&lt;/code&gt; to use as column headers for the table.&lt;/li&gt;
&lt;li&gt;Assumes &lt;code&gt;data&lt;/code&gt; has at least one object, and all objects have similar keys.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const tableColumnHeaders = Object.keys(data[0]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;5. Formatting Table Rows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Iterates over each object in &lt;code&gt;data&lt;/code&gt;, creating a new array (&lt;code&gt;tableRows&lt;/code&gt;) where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each entry corresponds to a row of the table.&lt;/li&gt;
&lt;li&gt;For each cell, if the value is an array, it joins elements with a comma; otherwise, it adds the value as is.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const tableRows = data.map((row) =&amp;gt;
    Object.keys(row).map((key) =&amp;gt; {
        const value = row[key];
        if (Array.isArray(value)) {
            return value.join(", ");
        }
        return value;
    })
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;6. Adding the Table to the PDF&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Configures the table with the following options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;startY&lt;/code&gt;: 50 positions the table 50 points below the top of the page.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;head&lt;/code&gt; uses tableColumnHeaders as the table’s header row.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;body&lt;/code&gt; is populated with tableRows, displaying data row-by-row.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;margin&lt;/code&gt; specifies spacing around the table.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;styles&lt;/code&gt; adjusts the cell font size, padding, and vertical alignment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;headStyles&lt;/code&gt; sets header row styles: blue background, white text, and 12-point font.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alternateRowStyles&lt;/code&gt; adds a light gray background for alternating rows.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;columnStyles&lt;/code&gt; attempts to set column width automatically.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;theme&lt;/code&gt;: "striped" applies a striped theme to the table.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;doc.autoTable({
    startY: 50,
    head: [tableColumnHeaders],
    body: tableRows,
    margin: { top: 50, left: 20, right: 20 },
    styles: {
        fontSize: 10,
        cellPadding: 5,
        valign: "middle",
    },
    headStyles: { fillColor: [41, 128, 185], textColor: 255, fontSize: 12 },
    alternateRowStyles: { fillColor: [245, 245, 245] },
    columnStyles: { auto: { cellWidth: auto } },
    theme: "striped",
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;7. Saving the PDF&lt;/strong&gt;&lt;br&gt;
Saves the PDF file with the filename "JS-pdf.pdf".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;doc.save(`${fileName}.pdf`);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the full version of this code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// App.jsx

import "./styles.css";
import { generatePDF } from "./pdf.jsx";

export default function App() {
 const generateUsers = (count) =&amp;gt; {
    const users = [];

    for (let i = 1; i &amp;lt;= count; i++) {
      const user = {
        id: i,
        firstName: `firstName_${i}`,
        lastName: `lastName_${i}`,
        email: `email_${i}@example.com`,
        address: [
          `Street ${i + 1}, Address Line 1`,
          `District ${(i % 7) + 1}, City_${i}`,
        ],
      };
      users.push(user);
    }
    return users;
  };

  const PdfGenerator = () =&amp;gt; {
    let jsonData = generateUsers(100);
    generatePDF(jsonData);
  };
  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;h1&amp;gt;Hello CodeSandbox&amp;lt;/h1&amp;gt;
      &amp;lt;h2&amp;gt;Start editing to see some magic happen!&amp;lt;/h2&amp;gt;
      &amp;lt;button onClick={PdfGenerator}&amp;gt;Print PDF&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Pdf.jsx

import jsPDF from "jspdf";
import "jspdf-autotable";


export const generatePDF = (data) =&amp;gt; {

  let fileName = "JS-pdf";
  const doc = new jsPDF("l", "pt", "a3");

  doc.setFontSize(16);
  doc.text("JSON Data PDF", doc.internal.pageSize.getWidth() / 2, 30, {
    align: "center",
  });

  const tableColumnHeaders = Object.keys(data[0])

  // Determine the table rows based on the values in data
  const tableRows = data.map((row) =&amp;gt;
    Object.keys(row).map((key) =&amp;gt; {
          const value = row[key];

          if (Array.isArray(value)) {
            return value.join(", ");
          }
          return value; // Return non-array values as is
        })
  );

  doc.autoTable({
    startY: 50,
    head: [tableColumnHeaders],
    body: tableRows,
    margin: { top: 50, left: 20, right: 20 },
    styles: {
      fontSize: 10,
      cellPadding: 5,
      valign: "middle",
    },
    headStyles: { fillColor: [41, 128, 185], textColor: 255, fontSize: 12 },
    alternateRowStyles: { fillColor: [245, 245, 245] },
    columnStyles: { auto: { cellWidth: auto } }
    theme: "striped",
  });

  doc.save(`${fileName}.pdf`);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is done for now. Hopefully, you enjoyed it. Have a nice day !!!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>react</category>
    </item>
  </channel>
</rss>
