Skip to main content

SDK Primer Part 2: Programming language guidance (JavaScript Coding Example)

Here is a working JavaScript example, From Zero to Hero, of creating a web automation accessibility test using our Level Access Testing SDK

On this page: 

About this example

Level Access Testing SDK for JavaScript is delivered as a single .js file. 

To learn more, go to https://tools.levelaccess.net/continuum/docs/latest/jsdoc/Continuum.js.html#line4531. Note that each programming language has at least one package management library.

Note: If you're using server-side JavaScript via something like Node, you must initialize Access Continuum differently than you would for client-side JavaScript via something like Karma, where the latter necessitates that Continuum be injected directly into the pages to be tested in a web browser.

Prerequisites

The following table lists the prerequisites you must meet: 

Prerequisite

Description

Google Chrome > v76.0

A popular web browser that you might already have installed.

Node.JS > v16.0

A popular server-side scripting environment for JavaScript.

NPM > v10.10: 

The node.js package manager. If you don't know the version of Node or NPM that you’re running, open a terminal and run the following commands:

node --version
npm --version

If you need to install node.js and npm for your own computer, use this procedure: Downloading and installing Node.js and npm

Sample test script with Selenium

Selenium is a core component of our SDK. In this example, the test script performs these steps:

  1. Navigate to duckduckgo.com.
  2. Scan the homepage.
  3. Type in a search term.
  4. Click search.

Create a basic script (web automation file)

To create a basic script, web_automation.js file, we need to configure npm, node, and ~/.npmrc.

To start creating a basic script:

  1. Create a new directory and change directories, cd into it.

    mkdir level-access-sdk-testing && cd level-access-sdk-testing
  2. Start a new project. Run this command:

    npm init -y
  3. Install selenium. Run this command: 

    npm install --save-dev selenium-webdriver
  4. Using a basic (not rich) text editor, create a new file, and save it to the same directory: web_automation.js
  5. Copy and paste the below into the file, and then save the file.  
const { Builder, By } = require('selenium-webdriver');

// Define a function that automates a test.
async function web_automation() {

    // Create a new web driver object to talk to chrome
    let driver = await new Builder().forBrowser("chrome").build();

    // .get tells the driver to make the web browser go to a website
    await driver.get("https://www.duckduckgo.com");

    // .findElement will locate an element using By.css
    // .sendKeys will type to that field found
    await driver.findElement(By.css("input[name='q']")).sendKeys("camping equipment");

    // Find the submit button and click it
    await driver.findElement(By.css("button[type='submit']")).click();

    // Pause for 10 seconds (10,000 ms), or else the window will close automatically.
    // Not necessary, but nice to see what the browser is doing at the end.
    await driver.sleep(10000);

    // Close the web browser driver
    driver.quit()
}

// Run the function above.
web_automation();
  1. Run the file in the terminal window:

    node web_automation.js

    Note: For this to work on OSX, chromedriver nneds to be the app that the fix is run on.

    You should see a Chrome browser appear, navigate to duckduckgo.com, and search for camping equipment (a search term in the file).  

    We now have the most basic web automation configuration. Our file structure should now look like this: 

level-access-sdk-testing/
  package.json
  package-lock.json
  web_automation.js

The package-lock file appears after the project is initialized and installed. 

Note: The file in this article contains multiple comments that describe what each line is doing. The line of code await driver.sleep(10000); is used to give you time to see what the browser is doing before the script completes and the browser closes. It delays for 10 seconds (10000 milliseconds). If you really wanted to, you could sprinkle that line anywhere within the web_automation() function to pause at any time:

// Pause for 10 seconds (10,000 ms), or else the window will close automatically.

    // Not necessary, but nice to see what the browser is doing at the end.

SDK integration

This section describes how to add Level Access Testing SDKs into your testing environment. 

You must complete these tasks: 

  1. Download and install the SDK
  2. Install a specific version of the SDK
  3. Configure SDK
  4. Use the SDK to test for accessibility

Download and install the SDK

The following table describes each term in the SDK package installation statement:  

Term

Definition

npm

The node package manager, which executes all commands, keywords, and flags.

install

The npm command to install a package.

--save-dev

A flag that tells npm to add what is being installed as a dependency to the project in the current directory.

@continuum/continuum-javascript-professional

The package to install.

@6.7.0

A specific version of the Continuum SDK to install. 

  • If the specific version is omitted, the latest version is downloaded. 

  • If a version is already installed, no further versions will be installed. 

Note: Adding a specific version is optional. Level Access generally recommends always using the latest version.

To download and install the SDK:

  1. Check to see if you have an .npmrc (NPM Runtime Configuration) file in your home directory. If not, create one using a plain text editor such as Notepad or vi (not Word or WordPad). To learn more about the file, go to npmrc. On *nix type systems your home directory is written as ~/. Hence, this file path should be ~/.npmrc.
  2. Another *nix feature is that files starting with a period (.) are hidden by default. Hence, if you are in the ~/ directory and type ls you won’t see your .npmrc file. Instead, you'll need to do ls -a to show all files, including your hidden .npmrc file.
  3. If your .npmrc file doesn’t already have it, add the Continuum repository to gain access by doing the following steps:
    1. Log in to the Level Access Platform using your favorite web browser
    2. From the platform navigation menu, under Manage, select Tools & Integrations, and then SDK.
    3. Under the JavaScript logo and title, select Download and Install.
    4. Copy the two Continuum repository access lines using the Copy button at the right. The lines should look like this: 

      
      @continuum:registry=https://npm.levelaccess.net/continuum/
      //npm.levelaccess.net/continuum/:_authToken=a2B3c5t67Hjkl

      The value of the authToken is unique to your account. Do not share it with anyone else.

    5. Check available versions. With the Continuum repository added to your .npmrc with a valid token, you can now check to see what versions are available. To do so, run this command: 
       

      npm view @continuum/continuum-javascript-professional versions --json 
      This should return a list that looks something like this:
      [
        '4.0.0', '4.0.1', '4.0.2', '4.1.0',
        '4.2.0', '4.3.0', '4.4.0', '4.5.0',
        '4.5.1', '4.7.0', '4.7.1', '4.7.2',
        '4.8.0', '4.9.0', '5.0.0', '5.0.1',
        '5.1.0', '5.1.1', '5.1.2', '6.0.0',
        '6.1.0', '6.1.1', '6.1.2', '6.2.0',
        '6.3.0', '6.4.0', '6.5.0', '6.6.0',
        '6.7.0', '6.8.0', '6.9.0', '7.0.0',
        '7.1.0', '7.2.0', '7.3.0'
      ]
    6. You can now install the latest version of Continuum to have it included in your package .json. Run this command: 

      npm install --save-dev @continuum/continuum-javascript-professional

Install a specific version of the SDK

To install a specific version of Access Continuum, add it to the end of the command like this:

npm install --save-dev @continuum/continuum-javascript-professional@6.7.0

Configure SDK 

We'll create a new file in the project root directory: continuum.conf.js. 

The following table describes the properties that you need to set in the continuum.conf.js file.  

Key 

Definition

orgInstanceUrl

The base organization URL, where the Level Access Platform services are located. This property is required and will be used for all scan sessions.

apiKey

The API key used in requests to the Level Access Platform services. This property is required and used for all scan sessions. To learn more about how to find the apiKey, go to Find API-parameters in the platform

workspaceId

The id or the workspace, which is when a scan session opens in the Level Access Platform. This property is optional and can be set here to apply to all scan sessions or provided / overridden programmatically when opening a new scan session.

digitalPropertyId

The id or the digital property used when a scan session opens in the Level Access Platform. This property is optional and can be set here to apply to all scan sessions or provided / overridden programmatically, when a new scan session opens.

scanTagId

The id or the scan tag used when a new scan session opens in the Level Access Platform. This property is optional. It can be set here to apply to all scan sessions or provided / overridden programmatically when a new scan session opens. To learn more about how to find the ScanTag ID, go to Find API-parameters in the platform

To configure the SDK:

  1. Paste the following into the continuum.conf.js file:
window.LevelAccess_AccessContinuumConfiguration = {
  "accessEngineType": "professional",
  "ampInstanceUrl": "https://amp.levelaccess.net",
  "defaultStandardIds": [
    610, /* WCAG 2.0 Level A */
    611, /* WCAG 2.0 Level AA */
    612, /* WCAG 2.0 Level AAA */
    1387, /* WCAG 2.1 Level A */
    1388, /* WCAG 2.1 Level AA */
    1389, /* WCAG 2.1 Level AAA */  
    2127, /* WCAG 2.2 Level A */
    2128, /* WCAG 2.2 Level AA */
    2129  /* WCAG 2.2 Level AAA */
    1140, /* Section 508 and 255 (Revised 2017) */
    1471 /* WCAG 2.0 Level A & AA Baseline */
  ],
  "includePotentialAccessibilityConcerns": false,
  "ampApiToken": null,

  "proxy": {
    "host": null,
    "port": null,
    "username": null,
    "password": null
  },
  "accessibilityConcerns": {
    "includePotentialConcerns": false,
    "format": "amp"
  },
  "levelAccessPlatform": {
    "orgInstanceUrl": "" ,
    "apiKey": "",
    "workspaceId": "",
    "digitalPropertyId": "",
    "scanTagId": ""
  }
}
  1. Review the bottom of the continuum.conf.js file. Find the following code, which needs to be filled in:   
"levelAccessPlatform": {
  "orgInstanceUrl": "",
  "apiKey": "",
  "workspaceId": "",
  "digitalPropertyId": "",
  "scanTagId": ""
}

The following table describes each property: 

Property Description

orgInstanceUrl

Sets the starting URL of your instance of the Level Access Platform. Required for scans to work. 

Example orgInstanceUrl: https://your_org_name.hub.essentia11y.com

apiKey

Your personal API key that you create in the Level Access Platform. Required for scans to work. It is tied to your user account and expires every six months.

To create your apiKey:

  1. Log in to the Level Access Platform using your favorite web browser.
  2. From the platform navigation menu, under Manage, select Tools & Integrations, and then API.
  3. Enter a name for the key and select Generate new API key.
  4. Copy the API key and paste it into the apiKey field in the configuration file.

Example apiKey: 4r44g305-cdd1-4513-a76b-478z22b3ejb5

workspaceId

Set the ID of the Workspace you want the results to be stored in. Setting it here makes it the default for all scans unless you supply a different workspaceId when making the individual scan calls. The value must be provided either in the config file or in the scan call for scans to work. 

To find the ID for your Workspace:

  1. Log in to the Level Access Platform using your favorite web browser.
  2. From the platform navigation menu, under Manage, select Tools & Integrations, and then API. Workspaces you have access to are listed, under Workspaces, digital assets and tags IDs.
  3. Copy the ID of the workspace you want to use and paste it into the workspaceId field in the configuration file.

Example workspaceId: 63416cfec1505527n10284a3

digitalPropertyId

Sets the ID of the digital asset (digital property) you want the results to be stored in. This digital asset must exist in the Workspace you specified. Setting it here makes it the default for all scans unless you supply a different digitalPropertyId when making the individual scan calls. The value must be provided either in the config file or in the scan call for scans to work.

To find the ID for your Digital Asset (previously known as Digital Property):

  1. Log in to the Level Access Platform using your favorite web browser.
  2. From the platform navigation menu, under Manage, select Tools & Integrations, and then API.  Workspaces you have access to are listed, under Workspaces, digital assets and tags IDs.
  3. Expand the Workspace where your digital asset is stored in to view all the available digital assets (previously called digital properties). 
  4. Copy the ID of the digital asset you want to use and paste it into the digitalPropertyId field in the config file

Example digitalPropertyId:  67533274378e413e26ff5g69

scanTagId

Sets the ID of the Scan Tag you want the results to be labeled with. This Scan Tag must exist in the Workspace you specified. Setting it here makes it the default for all scans unless you supply a different scanTagId when making the individual scan calls. The value must be provided either in the config file or in the scan call for scans to work. 

To find the ID for your Scan Tag:

  1. Log in to the Level Access Platform using your favorite web browser.
  2. From the platform navigation menu, under Manage, select Tools & Integrations, and then API.  Workspaces you have access to are listed, under Workspaces, digital assets and tags IDs.
  3. Expand the Workspace, and then the digital asset where your scan results are to be stored, to view all the available Scan Tags.
  4. Copy the ID of the Scan Tag that you want to use. Paste it into the scanTagId field in the configuration file. 

Example scanTagId: 6017fa50g984be58ffda7f85

Use the SDK to test for accessibility

Now that your continuum.conf.js file is populated with the needed values, we can begin feathering Level Access Testing SDK into your automated testing project. This involves importing the SDK, initializing it, and sprinkling accessibility testing at points of interest while the automation is running. Finally, send all the results to the Level Access Platform for review and processing. 

To test for accessibility:

  1. Open the web_automation.js file created earlier. To import the SDK into your project, add the following code as the second line of the file: 
const {Continuum} = require('@continuum/continuum-javascript-professional');

This code imports the object Continuum from the file path @continuum/continuum-javascript-professional. It pulls this in from a folder within the node_modules/ directory.

  1. After we’ve initialized the driver, we need the following line in the file to import our SDK configuration file:
await Continuum.setUp(driver, require('path').resolve(__dirname, "./continuum.conf.js"));

Note: We are assuming continuum.conf.js is in the same directory as web_automation.js. If you decide to store your continuum.conf.js elsewhere you must adjust the path in the call to .setUp(),  so that it can find where you placed it.

  1. Modify the web_automation.js file to add the following line of code to run an accessibility scan at points of interest in the automation:
await Continuum.runAllTests();

Typically, we want to do this after the page is loaded, and then again, after the search was run. 

The main idea is: 

  • Get your web page into a condition you want to test.

  • Run the accessibility test.

  • Repeat.

  1. View the results in the console. 

At this point we’ve pulled the SDK into our project, initialized them, and ran scans at interesting points during the automation. Now, we need to place these results somewhere, so that we can look at them. 

The simplest way is to log them to the console. To do so, add the following lines of code to the end of the web_automation.js file, inside the web_automation() function: 

const console_assertions = Continuum.getAssertions();
console.log(console_assertions);

Your web_automation.js file should now look something like this:


const { Builder, By } = require('selenium-webdriver');
const {Continuum} = require('@continuum/continuum-javascript-professional');


// Define a function that automates a test.
async function web_automation() {

    // Create a new web driver object to talk to chrome
    let driver = await new Builder().forBrowser("chrome").build();

    // Setup Continuum using the relative path of the continuum.conf.js file.
    await Continuum.setUp(driver, require('path').resolve(__dirname, "./continuum.conf.js"));

    // .get tells the driver to make the web browser go to a website
    await driver.get("https://www.duckduckgo.com");

    // Test the current page for accessibility
    await Continuum.runAllTestsForAssertions();

    // .findElement will locate an element using By.css
    // .sendKeys will type to that field found
    await driver.findElement(By.css("input[name='q']")).sendKeys("camping equipment");

    // Find the submit button and click it (searches and redirects the page)
    await driver.findElement(By.css("button[type='submit']")).click();

    // Test the current page for accessibility
    await Continuum.runAllTestsForAssertions();

    // Pause for 10 seconds (10,000 ms), or else the window will close automatically.
    // Not necessary, but nice to see what the browser is doing at the end.
    await driver.sleep(10000);

    // Close the web browser driver
    driver.quit()

    // Output all the findings to the console
    const console_assertions = Continuum.getAssertions();
    console.log(console_assertions);

}

// Run the function above.
web_automation();
  1. To execute your automated testing, now enriched with accessibility checks, run the following command in your shell:
node web_automation.js

You should see output that looks like this:

[
  { testId: '8', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '14', testType: 'AUTOMATIC', outcome: 'pass', results: [] },
  { testId: '15', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '16', testType: 'AUTOMATIC', outcome: 'pass', results: [] },
  { testId: '21', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '22', testType: 'AUTOMATIC', outcome: 'pass', results: [] },
  { testId: '26', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '27', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '28', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '31', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '33', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '34', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '35', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '37', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '38', testType: 'AUTOMATIC', outcome: 'pass', results: [] },
  { testId: '40', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '41', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '43', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '44', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '48', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '50', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '51', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '53', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '54', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '55', testType: 'AUTOMATIC', outcome: 'pass', results: [] },
  { testId: '57', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '59', testType: 'AUTOMATIC', outcome: 'pass', results: [] },
  { testId: '61', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '64', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '65', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '66', testType: 'AUTOMATIC', outcome: 'pass', results: [] },
  { testId: '67', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '69', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '71', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '74', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '78', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '80', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  { testId: '81', testType: 'AUTOMATIC', outcome: 'pass', results: [] },
  { testId: '83', testType: 'AUTOMATIC', outcome: 'na', results: [] },
  {
    testId: '85',
    testType: 'AUTOMATIC',
    outcome: 'fail',
    results: [ [Object], [Object], [Object], [Object], [Object] ]
  },

This output goes on for every test run. Expect a long list.

You could parse and process the test output in any way you wish either in the code of your test harness or via your own data analytics but it might be more useful to let the Level Access Platform do some of that lifting for you. Instead of just dumping the output to the console we can use the SDK to package up those results and push them to the platform.

  1. If you want, you can remove the console output lines from the previous step. 
  2. Before the driver.quit() line in web_automation.js,  add some code that'll create a scan session in the platform and store the findings in there.
    // Create an object to send results to the Platform. 
    const levelAccessPlatformReportingService = Continuum.LevelAccessPlatformReportingService;

    // Open a scan session with the Platform. 
    // We also give the name to our report here.
    await levelAccessPlatformReportingService.openScanSession({
        sessionName: 'Zero to Hero Demo'
    });

    // Grab the findings from the automated scan and upload them to the platform

    try {
        const assertions = Continuum.getAssertions();
        await levelAccessPlatformReportingService.submit(assertions);
    } finally {
        await levelAccessPlatformReportingService.completeScanSession();
    }

Note:

There is one gotcha here. Our example is interacting with and scanning duckduckgo.com and when outputting results to the console that works fine. Most clients won't have this domain in their list of allowed digital assets, so pushing results for this domain will probably fail. To fully complete this walkthrough, you'll need to modify the web_automation.js to use a digital asset that is allowed on your account. Ideally you would still do some manipulation of the page, but the approach will be the same whether you scan the page in its initial state or after having the Cucumber automation interact with it.

  1. Save the file, run it, and check the Level Access Platform, for the Organization, Workspace and Digital Asset configured in your continuum.conf.js. 

We should now see a new entry, that is, the scan results for our demo session Zero to Hero:

Level Access Platform Scan Results page for the accessibility scan we are running in this article.Shape

High-level script overview: What your file should look like

 Here’s what’s happened in the script we presented in this example:

Step Description
Test for assertions The Level Access Platform accepts test results in the form of assertions. For Continuum to produce test results in this format, you must call the runAllTestsForAssertions() method. This will return an array of Assertion objects.
Get the reporting service Submitting results to the Level Access Platform is done through a reporting service. You must retrieve an instance of the LevelAccessPlatformReportingService from Continuum by accessing the LevelAccessPlatformReportingService property. The returned reporting service instance allows you to open and complete scan sessions and submit the results.
Open a scan session Before you submit any test results to the Level Access Platform, you must have an active scan session opened. You can open a new scan session by calling the openScanSession() method on the LevelAccessPlatformReportingService instance retrieved from Continuum. You must provide a name for your scan session.
Submit results When you open a scan session, you can submit test results to the Level Access Platform. To do this, you can call the submit() method on the LevelAccessPlatformReportingService instance, retrieved from Continuum passing an array of Assertion objects. The supplied assertions will be posted to the Level Access Platform and stored as findings, for the URL the browser is currently at. The page title and screen dimensions are also automatically recorded and sent along with the assertions.
Complete the scan session When you have finished testing you can complete your scan session by calling the completeScanSession() method on the LevelAccessPlatformReportingService instance retrieved from Continuum.

If you followed each step in the example we provided, your file should look as follows:

const { Builder, By } = require('selenium-webdriver');
const {Continuum} = require('@continuum/continuum-javascript-professional');


// Define a function that automates a test.
async function web_automation() {

    // Create a new web driver object to talk to chrome
    let driver = await new Builder().forBrowser("chrome").build();

    // Setup Continuum using the relative path of the continuum.conf.js file
    await Continuum.setUp(driver, require('path').resolve(__dirname, "./continuum.conf.js"));

    // .get tells the driver to make the web browser go to a website
    await driver.get("https://www.duckduckgo.com");

    // Test the current page for accessibility
    await Continuum.runAllTestsForAssertions();

    //Fill out the search form
    // .findElement will locate an element using By.css
    // .sendKeys will type to that field found
    await driver.findElement(By.css("input[name='q']")).sendKeys("camping equipment");

    // Find the submit button and click it (searches and redirects the page)
    await driver.findElement(By.css("button[type='submit']")).click();

    // Test the current page for accessibility
    await Continuum.runAllTests();


    // Pause for 10 seconds (10,000 ms), or else the window will close automatically.
    // Not necessary, but nice to see what the browser is doing at the end.
    await driver.sleep(10000);

    // Create an object to send results to the Platform.
    const levelAccessPlatformReportingService = Continuum.LevelAccessPlatformReportingService;

    // Open a scan session with the Platform.
    // We also give the name to our report here.
    await levelAccessPlatformReportingService.openScanSession({
        sessionName: 'Zero to Hero Demo'
    });

    // Grab the findings from the automated scan and upload them to the platform
    try {
        const assertions = Continuum.getAssertions();
        await levelAccessPlatformReportingService.submit(assertions);
    } finally {
        await levelAccessPlatformReportingService.completeScanSession();
    }

    // Close the web browser driver
    driver.quit()
}
    // Output all the findings to the console
    const console_assertions = Continuum.getAssertions();
    console.log(console_assertions);


// Run the function above.
web_automation();

You now have a complete working example, From Zero to Hero, of creating a web automation accessibility test using our Level Access Testing SDK to run Access Engine. 

You can take what we have accomplished so far as a starting point and then mold it to fit into popular end-to-end testing frameworks. Proceed to SDK Primer Part 3: Testing framework guidance (Cucumber example).

Powered by Zendesk