ATM Guide

This guide will walk you through building and testing an Automated Teller Machine (ATM) application with CanJS’s
Core libraries. You’ll learn how to do test driven development (TDD)
and manage complex state. It takes about 2 hours to complete.

Setup

The JS Bin is designed to run both the application and its tests in the OUTPUT
tab. To set this up, the HTML tab:

Loads QUnit for its testing library. It also includes the <div id="qunit"></div>
element where QUnit’s test results will be written to.

Loads can.all.js, which
is a script that includes all of CanJS core under a single global can namespace.

Generally speaking, you should not use the global can script, but instead you
should import things directly with a module loader like StealJS,
WebPack or Browserify. Read Setting Up CanJS for instructions on how to set up CanJS in a real app.

Includes the content for an app-templatecan-stache template. This template
provides the title for the ATM app and uses the <atm-machine> custom can-component
element that will eventually provide the ATM functionality.

The JavaScript tab is split into two sections:

CODE - The ATM’s models, view-models and component code will go here.

TESTS - The ATM’s tests will go here.

Normally, your application’s code and tests will be in separate files and loaded
by different html pages, but we combine them here to fit within JS Bin’s limitations.

This step includes all the potential pages the state
property can transition between:

readingCard

readingPin

choosingTransaction

pickingAccount

depositInfo

withdrawalInfo

successfulTransaction

printingReceipt

Each of those states are present in the following state diagram:

We’ll build out these pages once we build the Card and Transaction sub-models that will make building the ATM view model easier.

Card tests

In this section, we will:

Design an API for an ATM Card

Write out tests for the card.

An ATM Card will take a card number and pin. It will start out as
having a state of "unverified". It will have a verify method
that will change the state to "verifying", and if the response is successful,
state will change to "verified".

Update the JavaScript tab to:

Make the fake data request delay 1ms by setting delay to 1 before every test and
restoring it to 2s after every test runs.

Write a test that creates a valid card, calls .verify(), and asserts the state is "verified".

Write a test that creates an invalid card, calls .verify(), and asserts the state is "invalid".

In this step, you implemented a Card model that encapsulates the behavior of its own state.

Deposit test

In this section, we will:

Design an API retrieving Accounts.

Design an API for a Deposit type.

Write out tests for the Deposit type.

An Account will have an id, name, and balance. We’ll use can-connect to add a
getList method that retrieves an account given a card.

A Deposit will take a card, an amount, and an account. Deposits will start out having
a state of "invalid". When the deposit has a card, amount and account, the state
will change to "ready". Once the deposit is ready, the .execute() method will change the state
to "executing" and then to "executed" once the transaction completes.

When complete, you should be able to enter a withdrawal amount and see that
the transaction was successful.

Optional: Challenge yourself by adding a test for the withdrawalInfo state of an atm instance. Consider the progression of states needed to make it to the withdrawalInfo state. How is it different from the ATM basics test we already have?

Transaction Successful page

In this section, we will:

Show the result of the transaction.

Update the HTML tab to:

List out the account balance.

Add buttons to:

start another transaction, or

print a receipt and exit the ATM (printReceiptAndExit will be implemented in the next section).