Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 17 additions & 18 deletions .github/workflows/_check_code.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Run actionlint
uses: rhysd/actionlint@v1.7.11

# TODO: Fix spell check after we merge current PRs
# TODO: Fix spell check after we merge current PRs
# spell_check:
# name: Spell check
# runs-on: ubuntu-latest
Expand All @@ -26,23 +26,22 @@ jobs:
# - name: Check spelling with typos
# uses: crate-ci/typos@v1

# TODO: Fix lint after we merge current PRs
# lint_check:
# name: Lint check
# runs-on: ubuntu-latest
# steps:
# - name: Checkout repository
# uses: actions/checkout@v6
# - name: Use Node.js
# uses: actions/setup-node@v6
# with:
# node-version: 24
# cache: 'npm'
# cache-dependency-path: 'package-lock.json'
# - name: Install dependencies
# run: npm ci
# - name: Lint
# run: npm run lint
lint_check:
name: Lint check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Use Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'npm'
cache-dependency-path: 'package-lock.json'
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint

type_check:
name: Type check
Expand Down
13 changes: 13 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
echo "pre-commit: typechecking, linting, testing, checking code formatting, checking for unused exports & validating schemas"


npm test
npm run format:check
# We typecheck & lint last when we know our code works
npx tsc --noEmit
npx lint-staged

# Activate once we resolv unused delete old builds
# npm run check-unused

echo "pre-commit: passed"
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
All notable changes to this project will be documented in this file.

<!-- git-cliff-unreleased-start -->

## 0.5.7 - **not yet released**

### 🚀 Features
Expand All @@ -14,8 +15,8 @@ All notable changes to this project will be documented in this file.

- Bump version to test beta release ([1322d31](https://github.com/apify/apify-test-tools/commit/1322d31873b6d43e16a68e97bdc358752f813f79)) by [@metalwarrior665](https://github.com/metalwarrior665)


<!-- git-cliff-unreleased-end -->

# Changelog

## 0.5.5
Expand Down Expand Up @@ -61,6 +62,7 @@ feat: feat: add maxRetriesPerRequest test
## 0.2.3

### Lib

- feat: add `runId` option to test tests
- fix: PPE pass won't override overall pass

Expand Down Expand Up @@ -89,4 +91,4 @@ feat: feat: add maxRetriesPerRequest test
### Cli

- fix: parsing commits
- feat: add `--workspace` cli option
- feat: add `--workspace` cli option
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Contributing

The package consists of two parts:

- cli located in `bin/`
- test library located in `lib`

Expand All @@ -22,6 +23,7 @@ The package consists of two parts:
### Development setup

1. Clone and build `apify-test-tools` repo:

```sh
git clone git@github.com:apify-projects/apify-test-tools.git
cd apify-test-tools
Expand All @@ -30,13 +32,15 @@ npm run build
```

For testing purposes, we use `testing-repo-for-github-actions` repo so that we don't mess with the production repos:

```sh
git clone git@github.com:apify-store/testing-repo-for-github-actions.git
```

#### Working on the CLI

To work on the library, you just need to define `GITHUB_WORKSPACE` to tell the cli where you repo is located:

```sh
export GITHUB_WORKSPACE=../path/to/testing-repo-for-github-actions # path to the repo
npx tsx bin/main.ts --help
Expand All @@ -46,6 +50,7 @@ npx tsx bin/main.ts get-commits --target-branch master --source-branch feat/test
#### Working on the library

You need to istall the local version of `apify-test-tools` in your cloned `testing-repo-for-github-actions`:

```sh
npm i -D ../path/to/apify-test-tools
```
Expand Down
82 changes: 39 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@
## Getting Started

1. Install the package `npm i -D apify-test-tools`
- because it uses [annotate](https://vitest.dev/guide/test-context.html#annotate), `vitest` version to be at least `3.2.0`
- because it uses [annotate](https://vitest.dev/guide/test-context.html#annotate), `vitest` version to be at least `3.2.0`
- make sure that `target` and `module` in your `tsconfig.json`'s `compilerOptions` are set to `ES2022`
2. create test directories: `mkdir -p test/platform/core`
- core (hourly) tests should go to `test/platform/core`
- daily tests should go to `test/platform`
3. setup github worklows TODO

File structure:

```
google-maps
├── actors
└── src
└── test
├── unit
└── platform
├── core <- Core tests need to be inside core directory
├── core <- Core tests need to be inside core directory
│ └── core.test.ts
├── some.test.ts <- Other tests can be defined anywhere inside platform directory
└── some-other.test.ts
Expand Down Expand Up @@ -73,7 +74,7 @@ name: PR Test

on:
pull_request:
branches: [ master ]
branches: [master]

jobs:
buildDevelAndTest:
Expand All @@ -88,7 +89,7 @@ name: Release latest

on:
push:
branches: [ master ]
branches: [master]

jobs:
buildLatest:
Expand All @@ -102,17 +103,18 @@ jobs:

### Test structure

To run the tests concurrently, we had to start the run outside of `it` and then call `await` inside. This is now no longer needed and everything can be inside `it` aka `testActor`.
To run the tests concurrently, we had to start the run outside of `it` and then call `await` inside. This is now no longer needed and everything can be inside `it` aka `testActor`.

Before:

```ts
({ it, xit, run, expect, expectAsync, input, describe }: TestSpecInputs) => {
describe('test', () => {
{
const runPromise = run({ actorId, input })
it('actor test 1', async () => {
const runResult = await runPromise;

// your checks
});
}
Expand All @@ -121,25 +123,26 @@ Before:
const runPromise = run({ actorId, input })
it('actor test 2', async () => {
const runResult = await runPromise;

// your checks
});
}
}
});
})
```

After:

```ts
import { describe, testActor } from 'apify-test-tools';

describe('test', () => {
testActor(actorId, 'actor test 1', async ({ expect, run }) => {
const runResult = await run({ input })

// your checks
)};

testActor(actorId, 'actor test 2', async ({ expect, run }) => {
const runResult = await run({ input })

Expand All @@ -155,6 +158,7 @@ describe('test', () => {
### Validating basic run attributes

Before:

```ts
await expectAsync(runResult).toHaveStatus('SUCCEEDED');

Expand All @@ -164,78 +168,70 @@ await expectAsync(runResult).withLog((log) => {
});

await expectAsync(runResult).withStatistics((stats) => {
expect(stats.requestsRetries)
.withContext(runResult.format('Request retries'))
.toBeLessThan(3);
expect(stats.crawlerRuntimeMillis)
.withContext(runResult.format('Run time'))
.toBeWithinRange(600, 600_000)
})

expect(stats.requestsRetries).withContext(runResult.format('Request retries')).toBeLessThan(3);
expect(stats.crawlerRuntimeMillis).withContext(runResult.format('Run time')).toBeWithinRange(600, 600_000);
});

await expectAsync(runResult).withDataset(({ dataset }) => {
expect(dataset.items?.length)
.withContext(runResult.format('Dataset cleanItemCount'))
.toBe(100);
})
expect(dataset.items?.length).withContext(runResult.format('Dataset cleanItemCount')).toBe(100);
});
```

After:

```ts
await expect(runResult).toFinishWith({
datasetItemCount: 100,
})
datasetItemCount: 100,
});
```

You can also specify a range:

```ts
await expect(runResult).toFinishWith({
datasetItemCount: { min: 80, max: 120 },
})
datasetItemCount: { min: 80, max: 120 },
});
```

Here is full example of what you can validate with `toFinishWith`

```ts
await expect(runResult).toFinishWith({
// These are default
// These are default
status: 'SUCCEEDED',
duration: {
min: 600, // 0.6 sec
max: 600_000, // 10 min
},
failedRequests: 0,
requestsRetries: { max: 3 },
forbiddenLogs: [
'ReferenceError',
'TypeError',
],

// only datasetItemCount is required
datasetItemCount: { min: 80, max: 120 },

forbiddenLogs: ['ReferenceError', 'TypeError'],

// only datasetItemCount is required
datasetItemCount: { min: 80, max: 120 },

// optional
chargedEventCounts: {
'actor-start': 1,
'place-scraped': 9,
},
})
'actor-start': 1,
'place-scraped': 9,
},
});
```

---

### Custom validations

Before:

```ts
expect(place.title)
.withContext(runResult.format(`London Eye's title`))
.toEqual('lastminute.com London Eye')
expect(place.title).withContext(runResult.format(`London Eye's title`)).toEqual('lastminute.com London Eye');
```

After:

```ts
expect(place.title, `London Eye's title`).toEqual('lastminute.com London Eye')
expect(place.title, `London Eye's title`).toEqual('lastminute.com London Eye');
```

---
Expand Down
Loading
Loading