Talking About TestingATT</>
JavaScript for QAs

Score 100% on the quiz to continue

Lesson
Free Preview

Data types

The primitives (undefined, null, Boolean, Number, String) and the structural types (Array, Object, Function) every test is built out of.

Everything in a test is a piece of data. The name you type into a field, the status code that came back, the list of rows in a table, the true-or-false answer to "is this button visible?".

JavaScript sorts all of that into a small number of types. Learn the types and most of the language's surprises stop being surprises.

There are two families: primitives and structural types.

Primitives

A primitive is a single, simple value. There are five you will use constantly.

String

Text. Written between single quotes, double quotes, or backticks.

console.log('Acme Corporation')
console.log("Acme Corporation")

Pick one style of quote and stay consistent. This course uses single quotes.

Number

Any number. JavaScript does not separate whole numbers from decimals: 42 and 3.14 are both just Number.

console.log(200)
console.log(19.99)
👨‍🏫 This is why a status code and a price are the same type. It also means 0.1 + 0.2 gives you 0.30000000000000004, which is not a JavaScript bug but how computers store decimals everywhere. Never assert on the exact result of decimal maths.

Boolean

Exactly two possible values: true and false. This is the type every assertion ultimately produces.

console.log(true)
console.log(false)

undefined

The value of something that exists but was never given a value. JavaScript assigns it for you.

let statusCode
console.log(statusCode)

That prints undefined. Nobody set it to anything.

null

The value of something deliberately set to "nothing". The difference from undefined matters: undefined means "nobody filled this in", null means "somebody filled this in with nothing".

const middleName = null
console.log(middleName)
👨‍🏫 In an API response, "phone": null means the field exists and the customer has no phone. A missing phone key gives you undefined instead, meaning the API did not send the field at all. Those are two different bugs, so it is worth being able to tell them apart.

Structural types

A structural type holds several values, in a structure. There are three you need.

Array

An ordered list. Written with square brackets, items separated by commas. The order is preserved, and positions are numbered from zero.

const sizes = ['Small', 'Medium', 'Large']

console.log(sizes[0])
console.log(sizes[2])
console.log(sizes.length)

That prints Small, then Large, then 3.

👨‍🏫 Counting from zero trips up everyone at the start. The first item is at index 0, so the last item of a three-item array is at index 2, never 3. Asking for sizes[3] gives you undefined.

An array can hold anything, including other arrays and objects. In testing, an array is usually a list of rows, a list of inputs, or a list of expected values.

Object

A collection of named values. Written with curly braces, as key: value pairs.

const customer = {
  name: 'Acme Corporation',
  size: 'Large',
  active: true,
}

console.log(customer.name)
console.log(customer.active)

That prints Acme Corporation, then true.

An object is what an API response body looks like, and what a piece of test data looks like. Arrays and objects nest inside each other freely: an array of customer objects is the single most common shape you will meet.

const customers = [
  { name: 'Acme Corporation', size: 'Large' },
  { name: 'Globex', size: 'Small' },
]

console.log(customers[1].name)

That prints Globex.

Function

A reusable block of code. In JavaScript a function is a value like any other, which is why it belongs in this list rather than in a chapter of its own.

function greet(name) {
  return 'Hello, ' + name
}

console.log(greet('Walmyr'))

That prints Hello, Walmyr.

👨‍🏫 The fact that a function is a value is the single most important idea in this course. It is what lets you pass a function to it(), to beforeEach(), and to forEach(). Lesson 7 covers functions properly.

How to check a type

typeof tells you what type a value is.

console.log(typeof 'Acme')
console.log(typeof 42)
console.log(typeof true)
console.log(typeof undefined)
console.log(typeof { name: 'Acme' })
console.log(typeof [1, 2, 3])
console.log(typeof null)

The last two are worth staring at. typeof [1, 2, 3] says 'object', not 'array', and typeof null also says 'object', which is a famous mistake in the language that can never be fixed without breaking the web.

To check for an array, use Array.isArray() instead.

console.log(Array.isArray([1, 2, 3]))
console.log(Array.isArray({ name: 'Acme' }))

That prints true, then false.

Syntax overview 📖

typeof

Returns a string naming the type of a value.

typeof 'Acme'

Array.isArray()

Returns true when the value is an array. The reliable way to check, since typeof cannot.

Array.isArray(['Small', 'Large'])

.length

The number of items in an array, or the number of characters in a string.

['a', 'b', 'c'].length
'Acme'.length

Accessing values

Square brackets and a number for arrays, a dot and a name for objects.

sizes[0]
customer.name

The testing part 🧪

Types are not academic. Here is the single most common false pass in web test automation, and it is a types problem.

Text read from a web page is always a String, even when it looks like a number.

it('shows the right total', () => {
  cy.get('[data-testid="total"]').invoke('text').then((total) => {
    // total is the string '42', not the number 42
    expect(Number(total)).to.equal(42)
  })
})

Without that Number() conversion, comparing '42' with 42 using a strict check fails, and comparing them with a loose check passes for reasons you did not intend. Lesson 4 covers exactly that difference.

The second place types matter is API testing, where knowing the expected type is the test.

it('returns a well-formed customer', async ({ request }) => {
  const response = await request.get('/api/customers/1')
  const customer = await response.json()

  expect(typeof customer.name).toBe('string')
  expect(typeof customer.active).toBe('boolean')
  expect(Array.isArray(customer.contacts)).toBe(true)
})

That test does not care what the customer is called. It cares that name is text, active is a true-or-false, and contacts is a list. If a backend change turns active into the string 'true', every UI check might still pass while this one catches it immediately.

👨‍🏫 A field that changes type is one of the nastiest bugs to find later, because the value still looks right when you print it. 'true' and true print identically.

Suggested content 📚

Exercise 🎯

Create 01-data-types.js in your fork and do the following:

  1. Declare one value of each primitive type: a string, a number, a boolean, an undefined, and a null
  2. Declare an array holding at least three strings, and print its length and its first item
  3. Declare an object describing a customer, with a name, a size, and whether it is active, and print two of its fields
  4. Print the typeof each of your five primitives
  5. Print Array.isArray() for both your array and your object

Run it with node 01-data-types.js, then commit and push it.

🙊 Here is one way to write it:
const name = 'Acme Corporation'
const employees = 240
const active = true
let notSetYet
const phone = null

const sizes = ['Small', 'Medium', 'Large']
const customer = { name: 'Acme Corporation', size: 'Large', active: true }

console.log(sizes.length)
console.log(sizes[0])
console.log(customer.name, customer.active)

console.log(typeof name, typeof employees, typeof active, typeof notSetYet, typeof phone)
console.log(Array.isArray(sizes), Array.isArray(customer))
Two things to notice in the output.

typeof notSetYet prints undefined even though nothing was assigned. That is JavaScript filling in the blank, not an error.

typeof phone prints object, not null. That is the language bug mentioned above. When you need to check for null, compare against it directly rather than trusting typeof.

Show the world what you learned 🌎

To show your professional network what you learned in this lesson, post the following on LinkedIn.

I started the "JavaScript for QAs" course by @Walmyr Lima e Silva Filho at the @Talking About Testing School, and the first lesson already explained a false pass I had seen before: text read off a page is always a string, even when it looks like a number, so comparing it to a number is not the check you think you wrote. #TalkingAboutTesting #TATSchool #JavaScriptForQAs #JavaScript #TestAutomation

👨‍🏫 Remember to tag me in your post. Here is my LinkedIn profile.

Quiz

Question 1 of 2
Score: 0

What does `typeof [1, 2, 3]` return, and what should you use instead?

Score 100% on the quiz to continue