# TypeScript library & unit tests

## Guide

In this guide, we will use the **Jest** testing framework in conjunction with the the "Basic TS Package" template (found in OXIDE) to create a reusable library that is also fully tested.

In the end, the package structure will look like this:

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-916dfa06fae23bb491e065ca2f6144a66837c8db%2Fpackages-jest-structure.png?alt=media)

### 1. Add the basic TS template package to your app

Navigate to the Packages workspace, or open the Packages panel, and create a new package. In the Package template dropdown, select "Basic TS Package" and proceed to follow the prompts. This created an app package with a basic framework to generate custom PDF reports.

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-c8ac26a5c5e6f56b969acbbfd240aa9f771dc1f3%2Fpackages-workspace.png?alt=media)

**Note**: you can also use the command palette to find the **Create package** action.

### 2. Export a function

Since this package represents a library, we will export a simple `sum` function inside the `src/index.ts` file

```typescript
export function sum(a: number, b: number) {
    return a + b;
}
```

### 3. Add a test

Now we create a new file called `tests/sum.test.ts` (OXIDE will create a new `tests` folder) and insert the following **Jest** code:

```typescript
import { sum } from "../src";

test('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).toBe(3);
});
```

### 4. Update the package.json file

To run Jest, we need to first add a few dependencies and make some changes in our `package.json` file. **Tip:** if you cannot see the `package.json` file, ensure that the **Show configuration files** setting in OXIDE is toggled on.

```json
{
    ...

    "scripts": {
      "build": "tsc -b && jest"
    },
    "main": "dist/src/index.js",
    "dependencies": {
      "jest": "^27.2.0",
      "@types/jest": "^22.2.3",
      "@babel/core": "7.15.5",
      "@babel/preset-env": "7.15.6",
      "@babel/preset-typescript": "7.15.0"
    },
    "jest": {
        "testMatch": [ "**/tests/**/*.test.ts" ]
    },

    ...
}
```

1. The `"build"` command is changed.
2. Our `"main"` entry now contains the 'src'
3. We add the latest versions of all the dependencies.
4. We add a `"jest"` field which tells **Jest** to find our tests correctly

### 5. Update the yarn lockfile

Because changes have been made to the `package.json` file, we must update the lock file using **yarn**.

In OXIDE, right click on the package, and select the update action as shown:

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-711560136d7ce91ee311b67ddc9a4bc99f06d3d8%2Fpackages-update-yarn.png?alt=media)

### 6. We configure Babel

When writing **Jest** tests using TypeScript, **Jest** will use **Babel** to transpile the files. For this reason we need to add a `babel.config.js` file with the following configuration:

```javascript
module.exports = {
    presets: [
        ["@babel/preset-env", { targets: { node: "current" } }],
        "@babel/preset-typescript",
    ]
};
```

### 7. We configure TypeScript

Since we now have TypeScript code in a tests folder, and have added a the `@types/jest` package, we need to make a few changes to the `tsconfig.json` file:

```json
{
    "extends": "@journeyapps/runtime-build/app-package.tsconfig.json",
    "compilerOptions": {
        "outDir": "dist",
        "types": ["jest"]
    },
    "include": [
        "./tests/*.test.ts",
        "./src/**/*.ts"
    ]
}
```

### 8. Use a function from the library within a view

Next we want to use the function that we've defined in the package library within a view. The below is an example of how to achieve this, by importing the relevant function(s) from the package into the view's TypeScript.

```typescript
import { sum } from "@local/unit_test"

// This function is called when the app navigates to this view (using a link)
async function init() {
    // initialize any data here that should be available when the view is shown
}

// This function is called when the user returns to this view from another view
async function resume(from: ResumeFrom) {}

async function calculateSum() {
    const a:number = 2;
    const b:number = 3;

    console.log(`Sum: ${sum(a, b)}`);
    // Sum: 5
}
```

### 9. Deploy!

Now when a testing deploy is triggered, not only will the library be built and accessible in your views, but the build will also only succeed if all tests pass.
