Turn your manual testers into automation experts Request a DemoStart testRigor Free

Astro Testing

Astro Testing

Businesses these days rely on extending their outreach through online apps and websites. The Astro framework is one such web development framework that acts as a one-stop solution for applications that need to support large content and require high performance. With Astro, you can achieve the best of both worlds, server-side and client-side rendering. Some of the major benefits of using Astro for web development are:

  • Focus on content: With Astro, you can build websites that are rich in content like blogs, portfolios, publishing sites, e-commerce sites, and marketing sites.
  • Preference for server-side rendering: Similar to traditional server-side rendering frameworks like PHP, Laravel, etc. Astro tries to follow a similar approach. However, this does not entail learning a server-side scripting language as Astro keeps it all in HTML, CSS, JavaScript, and even TypeScript.
  • Speed: Websites built using Astro are known for their speed. The code that is shipped using Astro is without JavaScript by default, thus making the page run faster. You can obviously override this and add your custom event listeners or other JavaScript elements. Astro is popular for its use of island architecture which rather than converting each page into a SPA requires the developer to break the page into islands. You have the freedom to mix and match the UI technologies supported by Astro to create different islands. Thus the vast majority of your application is simple and fast. The portions that require interactivity are provided with it, thus keeping in check the overall performance of the application.
  • Easy to use: Astro supports other popular UI component languages such as React, Vue, Svelte, Solid, Lit, Preact, and many others. Thus Astro gives you the flexibility to build by writing components using other languages or by using the Astro library and components.
  • Fully featured, yet flexible: Astro comes with all the gizmos to let you build your web application, ship it and even scale it. However, it also offers a varied platter of add-ons that you can choose from to extend your workspace.

Once you have developed your application, you need to test it. Astro offers support for all the well-known testing frameworks, even those that are specific to development frameworks like the React Testing Library for React. Testing can be done by performing:

Unit Testing

Unit testing acts as the first line of defense in the quality control process. If we refer to the testing pyramid, then unit testing forms the base of the pyramid, meaning that these tests are more in number, covering a very vast ground. As the name suggests, you need to test small units of code like functions or classes. These tests are supposed to be very concise and straightforward when it comes to input and output. It is a good practice to make sure that each of your unit tests expects a single outcome. This may seem tedious but when it comes to larger applications, if any of the unit tests fail, you will be able to pinpoint the issue and scenario with ease.

Astro is compatible with a lot of testing frameworks. Let's take a look at a few of the popular options that they are known to support. Most of these frameworks and libraries are used together to achieve better results.

Jest

Jest is one of the most popular JavaScript testing frameworks that is used to test code written using React, Babel, Vue, Node, Angular, TypeScript, and more. Using Jest you can avail powerful matchers and assertions, asynchronous testing support, identify code coverage, rich mocking functions to mimic elements out of the test scope, and integration with other tools and frameworks.

Vitest

Vitest is a Vite-native framework that is also compatible with Jest. It is useful for testing component code built using Vue, React, Svelte, Lit, and more. It makes use of Vite's config, transformers, resolvers, and plugins. Vitest supports mocking using Tinyspy, identifying code coverage using v8 or istanbul, multithreading using Tinypool, concurrent running of tests, and many other capabilities.

Here is a simple example of a unit test using Vitest with Astro. It creates an object input with properties foo and bar, serializes it using JSON.stringify(), and asserts that the output matches the expected JSON string {"foo":"hello","bar":"world"}. Additionally, it uses assert.deepEqual() to confirm that parsing the output JSON results in an object identical to the original input object.
import { assert, expect, test } from 'vitest';

test('JSON', () => {
  const input = {
    foo: 'hello',
    bar: 'world',
  };
  
  const output = JSON.stringify(input);
  
  expect(output).eq('{"foo":"hello","bar":"world"}');
  assert.deepEqual(JSON.parse(output), input, 'matches original');
});

Mocha and Chai

Mocha and Chai are quite often used together to test JavaScript code. Mocha is a popular JavaScript testing framework that provides a flexible and feature-rich environment for writing tests. You can easily install this framework into your project while further integrating it with assertion libraries like Chai to improve validation and testing. With Mocha, you can perform mocking easily, do synchronous and asynchronous testing, and more. When clubbed with a powerful assertion library like Chai, you can gain access to a vast library of assertions. Another great thing about using Chai is that it has BDD and TDD-specific assertions to help with those forms of testing.

Jasmine

Jasmine is a well-known testing framework that is used for JavaScript testing. Though it is known to facilitate BDD-style testing, it can be used for writing unit and integration tests as well. It is popular among front-end developers working heavily with Angular but is also used with other JavaScript frameworks. Besides offering a list of matchers and assertions, Jasmine lets you create custom equality checkers, matchers, object formatters, and reporters. It uses a descriptive style with functions like describe, it, expect, and beforeEach that make the tests more expressive and self-documenting. Tests in Jasmine are organized into suites and specs. A suite, defined using the describe function, represents a logical grouping of related specs. Each spec, defined using its function, represents an individual test case. Using Jasmine's spying and mocking system, you can create test cases with ease.

Component Testing

A modern web application comprises various components which could include something as small as an input field to a more complex variation as a registration form. These components are whole in themselves and can be tested without too many dependencies. Sometimes, you might need to test interactions between various components to achieve a larger outcome like a date picker which forms a part of the registration form.

Component tests are mostly written by developers who work on those components. These tests might require some level of mocking depending on what kind of dependencies are expected in the scenario under test. Since Astro supports many popular UI development frameworks, you can use different testing frameworks and libraries to write component tests.

Most unit testing frameworks also support component testing. You can make use of the frameworks we discussed above in the unit testing section like Vitest, Jest, Mocha, Chai, Jasmine, and React Testing Library to do this. Besides these, some end-to-end testing tools like Cypress and Playwright also support this kind of testing.

Cypress offers a special component testing mode wherein you can set up components directly from your UI development frameworks. This mode is also faster than the end-to-end testing mode since it builds the components using the developer server instead of a website, thus resulting in fewer dependencies. Here is a simple example of checking the text displayed in a button component from Angular.
import ButtonComponent from './button.component'

it('uses custom text for the button label', () => {
  cy.mount('<app-button>Click me!</app-button>', {
    declarations: [ButtonComponent],
  })
  cy.get('button').should('contains.text', 'Click me!')
})

Like Cypress, Playwright too supports component testing and offers mocking and test fixtures to help with the testing process. We will see more about Cypress and Playwright in the next section.

End-to-End Testing

Unlike the above two modes of testing, end-to-end testing exercises all layers of the application, rather than being restricted to certain functions or components. This means that the focus here is on use cases that are run by the end user and not the system developer. These tests take longer to execute than unit or integration tests and are usually fewer in number compared to them.

You can find many tools in the market that offer capabilities for end-to-end testing. In this section we will be looking at some of the best fits for your Astro project.

Cypress

Cypress is used for end-to-end testing and is a well-known choice due to its developer-friendly syntax, powerful debugging capabilities, and comprehensive testing features. You can integrate Cypress into your Astro project through a package manager of your choice. In the root of your project, a configuration file by the name of cypress.config.js with the following details needs to be present:
import { defineConfig } from 'cypress'
	
export default defineConfig({
  e2e: {
    supportFile: false
  }
})

Once this is done, you can go ahead to create tests under the cypress/e2e folder. Remember to name your test files as fileName.cy.js. You can run your Cypress tests either from the CLI or the Cypress application. If you use the application, you can take advantage of the visual UI and features that Cypress provides for running and debugging tests.

In the following example, we visit a specific URL, perform a click action, and verify the resulting URL. After pausing the test execution, we interact with an email input field and check if the value of the field is updated correctly.
describe('page test - suite', () => {
  it('Visits page', function () {
    cy.visit('https://example.cypress.io')
    cy.contains('type').click()
    cy.url().should('include', '/commands/actions')
    
    cy.pause()
    
    cy.get('.action-email')
      .should('have.value', '')
      
      cy.get('.action-email')
        .type('fake@email.com')
        .should('have.value', 'fake@email.com')
  })
})

Playwright

Like Cypress, Playwright supports cross-browser end-to-end testing. Playwright provides a rich set of automation features like page navigation, form filling, element interaction (clicking, typing, or selecting), screenshots, PDF generation, network interception, and more. It gives you control over browser behavior and allows you to simulate complex user interactions.

You can install Playwright through a package manager like npm, pnpm, Yarn, or through VS code extension. Once that is done, set up your playwright.config.ts file and the test folder in which you will create your test cases. The following test case demonstrates the process of filling out a profile setup form, making changes, and verifying that the changes are saved.
test("Can fill out the profile setup form and have changes saved", async ({
  page,
  baseURL,.
  existingUser: _,
}) => {
  await page.goto(`${baseURL}/profile-setup`);
  
  const $unsavedText = page.locator("text=You have unsaved changes");
  const $savedText = page.locator("text=Changes saved!");
  const $saveBtn = page.locator("text=Save Profile");
  
  await page.setInputFiles("#avatar-file", "./test/fixtures/images/avatar.avif");
  await expect.soft($savedText).toBeVisible();
  const avatarSrc = await page.locator('img[alt="Your Profile Photo"]').getAttribute("src");
  expect(avatarSrc).not.toBeFalsy();
  
  const $locationInput = page.locator('[name="location"]');
  await $locationInput.fill("Akron, OH");
  await expect($saveBtn).not.toBeDisabled();
  expect($unsavedText).toBeVisible();
  await $locationInput.press("Tab");
  
  await $saveBtn.click({ force: true });
  await expect($savedText).toBeVisible();
});

testRigor

Cypress and Playwright are good frameworks for end-to-end testing and do offer a lot of features. However, if you're seeking something more cutting-edge that's easier to scale and onboard, testRigor might be just the framework for you. As a cloud-based application, testRigor can be accessed effortlessly, eliminating on-premise setup complications. Furthermore, you don't need to concern yourself with the underlying development framework since testRigor's test cases interact with the application through the UI, thereby eliminating the need to create configuration files in the application code.

End-to-end tests are not as simple as unit tests, which are straightforward input-output test cases. Rather, they represent user journeys, which are often better understood by business teams like product owners or manual QAs. The aforementioned end-to-end testing frameworks heavily rely on the user having coding experience. To address this limitation, testRigor allows you to write test scripts in plain English. This makes it easier for team members with diverse backgrounds to collaborate and participate in the testing process.

For larger applications that require test case organization, testRigor lets you create test suites, which can be used to group test cases. At the test suite level, various configurations are available, such as authorization parameters, URL to test, browser and platform configurations, and more. If you need to test with data, provisions are available for creating test data either through testRigor's UI or by file upload.

Since testRigor supports testing across platforms like the web, mobile, and desktop, you will find the framework packed with commands that help with different scenarios. For example, if you are working with a web application, you could use something like 'double click on the 3rd "hello"' or 'hover over 3rd "element"'. Or if you are working with a mobile application, you might need to use something like 'long press on the 3rd "element"' or 'swipe down on "right_panel"'. Besides these basic commands, testRigor makes working with table data easy. Here's an example.
click "Open channel" within the context of second table at row "103" and column "Action"
check that the second table at row containing "Nyota" and column "Action" contains link "Open channel"

Apart from these capabilities, you can use testRigor to perform visual testing, accessibility testing, writing test cases that require 2-factor authentication or login support, mocking API calls, basic interactions with the database, and testing phone calls, email, or SMS content. Another feature that comes in handy is reusable rules, a concept similar to reusing functions in coding. The best part over here is that your commands that will be part of the reusable rule are all plain English statements. These rules can be used across test cases in a suite.

The above Playwright example for an end-to-end test case which uploads a profile picture and updates the location input field will look like this when written in testRigor:
open url "https://samplesite/profile-setup"  
enter stored value "avatar picture" into input file "file"
compare image of "avatar" to stored value "avatar picture" with allowance of "5%"
enter "Akron, OH" into "Location"
check that page contains stored value "warning text"
check that button "Save" is enabled
click "Save"

You can easily interact with your UI and get seemingly complicated actions like file uploading done with a single command. testRigor also provides a clear reporting system in the form of video captures for every test case and screen captures for every test step. Higher level reporting at a test suite level is included also.

Overall, testRigor is the easiest and most robust way to ensure end-to-end coverage for Astro applications.

Conclusion

When scouting for a test automation framework, one does look at factors like cost efficiency, ease of use, targeted users, out-of-the-box features, and scalability. Luckily most modern web development frameworks like Astro can easily integrate with most of the test automation frameworks. Moreover, if you decide to pick a framework like testRigor, you need not even worry about compatibility and can rest assured knowing that test case creation and maintenance is going to be a piece of cake for you.