An API first tests runner for Node.js
Japa is an API first testing framework. It focuses only on testing Node.js (backend) applications, thus resulting in a fast, small, and a simple tests runner.
Standalone test runner built on top of japa core
License: MIT License
An API first tests runner for Node.js
Japa is an API first testing framework. It focuses only on testing Node.js (backend) applications, thus resulting in a fast, small, and a simple tests runner.
I don't know if this is a bug or not but all tests are failing when I set up the adonis application on a different location or PC or in case I delete the node_modules
directory and re-install the npm dependencies. At the moment, I found two issues :
route
from the test context is getting undefined.loginAs
function is not working. test('Need email|mobile & password to login.', async ({ client, route }) => {
const response = await client.post(route('api.login')).accept('json')
response.assertStatus(422)
response.assert?.containsSubset(response.body(), {
errors: [{ field: 'email' }, { field: 'password' }],
})
})
test('An authenticated user can see the list of categories too.', async ({ client, assert }) => {
const categories = await CategoryFactory.createMany(5)
const user = await UserFactory.create()
const response = await client.get('/api/categories').loginAs(user).accept('json')
response.assertStatus(200)
response.assert?.equal(5, response.body()?.length)
assert.containsSubset(response.body(), categories.map(({ id, type, name }) => ({ id, type, name })))
})
These tests were passing when I set up the fresh AdonisJS application but failed after re-installing dependencies/relocating by repo clone. I have attached two screenshots of the test results.
If route
and loginAs
functions were passing before push (Push to git repo) then it should be working when I clone the code and installl the dependencies in another location or PC.
route
from the test context and loginAs
in test suite body. Tests should be passing.node_modules
directory OR move application files to the new location without node_modules
directory and install dependencies via yarn
node ace test
and the above two test examples will fail.v2.0.7
3.0.0-9
Is there a flag to stop the runner and print the errors after the first test failure?
No response
While trying to use esno with typescript I'm getting stuck on an error.
japa 0.14.1
β― esno .\bin\test.ts
Unknown file extension ".ts" for C:\Users\xo\code\omgimalexis\scratch-pad\tests\maths.spec.ts
at async importFiles C:/Users/xo/code/omgimalexis\scratch-pad/node_modules/@japa/runner/build/index.js:241
236| if (isFileAllowed(file, runnerOptions.filters.files)) {
237| await runnerOptions.importer(file);
238| }
239| }
240| else {
> 241| await runnerOptions.importer(file);
242| }
243| }
244| }
245| /**
246| * Run japa tests
I needed to apply the fix from #2 first.
Hey !
I started to take a quick look at writing a snapshot testing plugin for Japa.
I was quickly confronted with this problem. It seems to me that we have no API to retrieve the name of the test/group, as well as the name of the file currently executed.
I need this information to write a snapshot file next to the executed test file, and its content must include the name of the executed test.
I think we could have something quite similar to the Tracker (or use this class but maybe split the "report summary generation" aspect into another class).
What do you think about it? Do you have any better recommendations?
Hello guys. I have a project here in GitHub that is using ESM. Every commit to this project triggers a GitHub Actions CI pipeline that runs the Japa tests in Linux environment and then in Windows environment.
2.0.7
In Linux environment everything works well. But on Windows, I'm facing this error:
I think it is a little hard to reproduce this problem because it is happening only on Windows. But here is it:
Currently, the database migrate
runner hook shows the output for migrate
and rollback
in terminal which is very annoying. I have to scroll a lot to find the test runs and their results. There should be option to omit these outputs or need to hide permanently.
tests/bootstrap.ts
/*
|--------------------------------------------------------------------------
| Runner hooks
|--------------------------------------------------------------------------
|
| Runner hooks are executed after booting the AdonisJS app and
| before the test files are imported.
|
| You can perform actions like starting the HTTP server or running migrations
| within the runner hooks
|
*/
export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
setup: [() => TestUtils.ace().loadCommands(), () => TestUtils.db().migrate()],
teardown: [],
}
Assertion method parameter orders should be predictable. I have hard time following if expected is first or second parameter.
equal:
parameters[0]: actual
parameters[1]: expected
includeOrderedMembers:
parameters[0]: expected
parameters[1]: actual
"@japa/preset-adonis": "^1.0.15",
"@japa/runner": "^2.0.7",
3.0.5
The docs mention importing reporters from @japa/runner/reporters
, but this nested module import does not seem to have a type declaration. Using the import still works however.
Example config
import { configure, processCLIArgs, run } from '@japa/runner';
import { spec } from '@japa/runner/reporters';
processCLIArgs(process.argv.slice(2));
configure({
files: ['src/test/**/*.spec.ts'],
reporters: {
activated: ['spec'],
list: [spec()],
},
});
(async () => {
await run();
})();
Shows an intellisense error Cannot find module '@japa/runner/reporters' or its corresponding type declarations. ts(2307)
No response
When doing a npm init japa
command (docs: https://www.npmjs.com/package/create-japa), if @japa/browser-client
plugin is selected, the initialization fails with a playwright error:
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: process.cwd()@0.0.0
npm ERR! Found: [email protected]
npm ERR! node_modules/playwright
npm ERR! dev playwright@"1.43.0-alpha-1709823751000" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer playwright@"^1.38.1" from @japa/[email protected]
npm ERR! node_modules/@japa/browser-client
npm ERR! dev @japa/browser-client@"2.0.0-4" from the root project
No response
Runs tests related to the changes since the provided branch or commit hash. If the current branch has diverged from the given branch, then only changes made locally will be tested
Jest has this feature and it's super useful.
It considerably reduces CI testing time.
https://jestjs.io/docs/en/cli.html#--changedsince
3.1.1
In Node.js, given a plugin configuration such as:
configure({
files: ['tests/**/*.test.ts'],
plugins: [assert()],
});
The TestContext
object is augmented with an "assert" property:
TestContext.getter('assert', () => new Assert(), true)
However, when running the test script using Deno, the test context which is passed to the test function does not have this property β see this failing test run.
When looking at the code, I see that @japa/assert uses import { TestContext } from '@japa/runner/core'
while the code that's creating the test context uses import { TestContext as BaseTestContext } from '@japa/core'
.
Somehow this works in Node.js but not in Deno β but why? I understand that Deno may not be a target runtime for Japa, but I came to Japa because Jest does not work in Deno (see this issue which discusses some of the problems).
N/A
This isn't a bug with japa
itself, but rather the repository issue configuration.
Steps to reproduce::
New Issue
, be brought to https://github.com/japa/runner/issues/new/chooseFeature Request
Actual Functionality:
Expected Functionality
So basically its currently not possible to file a feature request issue with the current UI, you just end up back on the issue type selection page.
No response
2.2.1
When trying to upload a file that doesn't exist, the test runner hangs and never prints a summary or exits the process. This used up all my GitHub action minutes whilst I slept last night :(
import { join } from "node:path";
import { test } from "@japa/runner";
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
test.group("Service Provider Profile", async (group) => {
// In my app I'm doing a database transaction
// ------------------------------------------
// group.each.setup(async () => {
// await Database.beginGlobalTransaction();
// return async () => await Database.rollbackGlobalTransaction();
// });
// but this is needed to trigger the hang
// without this setup the hang does not occur
// ------------------------------------------
group.each.setup(async () => {
await sleep(1);
return async () => await sleep(1);
});
test("upload hangs", async ({ client }) => {
await client
.post(`/api/v1/upload`)
.file("avatar", join(__dirname, "../does/not/exist/", "file.jpg"));
});
});
There is a reproduction repo. Simply clone npm install
and run node ace test
.
2.2.1
Hi,
I've a bug with using APIClient when i test a route API contains a slug /admin/clients/:id
On my OpenAPISchema i define also a route with slug like this
path:
/admin/client/{id}:
or
path:
/admin/client/:id:
But you can see on the screenshot, he don't find the route because he's search with the id
not with the slug
Thank you
No response
Its been more than a year since we released Japa v2 (a rewrite). Now, we have collected some ideas and a plan to migrate to ESM, so it feels like the perfect moment for v3.
Note: Migrating from Japa v2 to v3 will be relatively simple, with the only exception of moving from CJS to ESM. If your apps are already in ESM, then migrating should be a few minutes task.
Note: Have a feature in mind? Feel free to comment in this issue, we will see if it can make its way to v3.
As Node.js ecosystem is moving to ESM, it is becoming harder to rely on dependencies that works with CommonJS. As a side-effect, sometimes we cannot get security patches, or get deprecation warnings.
Moving to ESM is really not a choice. We can delay it, but it has to happen one day.
We will rewrite the Japa packages in ESM, therefore, the host application (the one using Japa) has to use ESM as well in order to import Japa inside the codebase.
We have to cleanup the internals of the @japa/runner
package. Since, most of the hard work is done by @japa/core
, I went lazy and dumped all the code of the runner package in one file.
But, I think, we should clean it up now and make it more streamlined.
Update: The codebase is a lot cleaner and well organized now. c57d344
The test runner seems to break when an error is thrown within a function irrespective of the assertion, assert.throws
, being used.
For example: I have a simple function which throws an error when the permission
is not found in a stub file:
export const getPermission = function (name: string) {
const permission = permissions.find((p) => p.name === name)
if (!permission) {
throw new RangeError(`Provided permission "${name}" is invalid`)
}
return permission.name
}```
And the following unit test:
```ts
test('should throw error if the permission name if invalid', async ({ assert }) => {
assert.throws(() => getPermission('Can List All Users'))
})
})```
## Package version
"@japa/api-client": "^1.3.1",
"@japa/assert": "^1.3.4",
"@japa/preset-adonis": "^1.0.16",
"@japa/run-failed-tests": "^1.0.7",
"@japa/runner": "^2.0.8",
"@japa/spec-reporter": "^1.1.12",
## Error Message & Stack Trace
```text
Provided role "Global Enterprise Manager" is invalid
at getRole app/Services/AccessControlService.ts:15
10| }
11|
12| export const getRole = function (name: string) {
13| const role = roles.find((p) => p.name === name)
14| if (!role) {
β― 15| throw new RangeError(`Provided role "${name}" is invalid`)
16| }
17| return role.name
18| }
19|
20| export const PERMISSIONS = {
I've tried injecting stuff into the test context and it worked. But this is not documented, is this a bad pattern?
test.group("foo endpoint", (group) => {
group.each.setup(async (test) => {
const drive = Drive.fake("gcs");
// @ts-ignore
test.context.drive = drive;
return () => Drive.restoreAll();
});
test("mocked disk test", async ({ test: { context } }) => {
// @ts-ignore
console.log(context.drive); // πprints actually
});
});
Alternative is getting the instance in the test scope but restoring everything at the teardown, I guess. But it feels weird to copy paste drive mocking setup in each test.
test.group("foo endpoint", (group) => {
group.each.teardown(async (test) => {
Drive.restoreAll();
});
test("mocked disk test", async ({ test: { context } }) => {
const drive = Drive.fake("gcs");
// send request here
// assertions
assert.equal(await drive.get('package.json'), JSON.stringify({}))
// let the teardown hook do the cleanup
});
});
v2.0.7
next
This is feature request, not a bug report (for some reason Feature Request temple does not work).
I was looking for a lighter testing framework for a CLI tool. Japa looks like a good candidate, because of snapshots and FS wrapper. Most of the test I have are e2e tests. The CLI tool runs in a spawned process and I snapshot stderr / stdout. (Also in many cases fixture files have to be written and clean up.)
A single test checks both stderr and stdout in separate snapshots. I was wondering if it would be possible to add snapshot hint
similar to what Jest has: https://jestjs.io/docs/next/expect#tomatchsnapshotpropertymatchers-hint
import { test } from "@japa/runner";
test("handles feature", async ({ assert }) => {
const { exitCode, stderr, stdout } = await spawn(fixtureUrl, ["feature"]);
assert.snapshot(normalizeOutput(stderr)).match("stderr"); // <- hint could be used here
assert.snapshot(normalizeOutput(stdout)).match({ hint: "stdout" }); // <- might be even better to pass it as an option
assert.equal(exitCode, 0);
});
No response
As a user of japa I would like to quickly look up the documentation for the CLI by using the standard -h
and --help
commands. This improves both the ergonomics and is less surprising to the user. I was surprised when I included the help flag and instead of spitting out the help text it ran all my tests.
4.0.0
Hi,
When I try to use project's root folder to set up runner config, I'm getting the following error
ReferenceError: describe is not defined
β Object.<anonymous>
node_modules/json-schema-traverse/spec/index.spec.js:6
β async importFiles
node_modules/@japa/runner/build/index.js:151
My bin/test.js
file looks like
import { assert } from '@japa/assert'
import { pathToFileURL } from 'node:url'
import { apiClient } from '@japa/api-client'
import { specReporter } from '@japa/spec-reporter'
import { processCliArgs, configure, run } from '@japa/runner'
configure({
...processCliArgs(process.argv.slice(2)),
...{
files: ['./**/*.spec.js'],
plugins: [assert(), apiClient('http://localhost:3333')],
reporters: [specReporter()],
importer: (filePath) => import(pathToFileURL(filePath).href),
},
})
run()
No response
I am trying to automate the test runner in my github workflow and it will exit with an error on ace commands. Running the test runner locally works as expected.
Not sure if I should have posted this here or in the adonis repo itself.
Even if there is a decent example of setting up running tests with the db for a github workflow, that would be greatly appreciated.
^4.0.0
Error: Command failed with exit code 1: node ace migration:run
at makeError (/home/runner/work/portal-api/portal-api/node_modules/execa/lib/error.js:60:11)
at handlePromise (/home/runner/work/portal-api/portal-api/node_modules/execa/index.js:118:26)
at processTicksAndRejections (internal/process/task_queues.js:[95](https://github.com/DirectLink-AI/portal-api/runs/5773496600?check_suite_focus=true#step:7:95):5)
at runMigrations (/home/runner/work/portal-api/portal-api/japaFile.ts:32:3)
at run (/home/runner/work/portal-api/portal-api/node_modules/japa/build/src/SlimRunner/index.js:107:9) {
shortMessage: 'Command failed with exit code 1: node ace migration:run',
command: 'node ace migration:run',
escapedCommand: 'node ace "migration:run"',
exitCode: 1,
signal: undefined,
signalDescription: undefined,
stdout: undefined,
stderr: undefined,
failed: true,
timedOut: false,
isCanceled: false,
killed: false
}
Just to note, I have a .env.testing
file for any necessary environment variables for my application
I have in my workflow already set up postgres, node, and installed the dependecies:
name: validate-pull-requests
on:
pull_request:
branches:
- dev
- staging
- main
jobs:
lint-test-build:
runs-on: ubuntu-latest
services:
postgres:
image: postgres
env:
POSTGRES_USER: root
POSTGRES_PASSWORD: root
POSTGRES_DB: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: '14.19.0'
- name: Install Dependecies
run: npm install
- name: Run Linter
run: npm run lint
- name: Run Tests
run: npm run test
- name: Run the build
run: npm run build
and here is my japaFile in order to set up the test dbs and run the migrations:
import 'reflect-metadata'
import pgtools from 'pgtools'
import execa from 'execa'
import { join } from 'path'
import getPort from 'get-port'
import { configure } from 'japa'
import sourceMapSupport from 'source-map-support'
process.env.NODE_ENV = 'testing'
process.env.ADONIS_ACE_CWD = join(__dirname)
sourceMapSupport.install({ handleUncaughtExceptions: false })
const dbConfig = {
user: 'root',
password: 'root',
port: 5432,
host: 'localhost',
}
const handleDBCallback = (error, result) => {
if (error) console.log(error.message)
else console.log(result)
}
async function createTestDbs() {
pgtools.createdb(dbConfig, 'test', handleDBCallback)
pgtools.createdb(dbConfig, 'dl-test-1', handleDBCallback)
pgtools.createdb(dbConfig, 'dl-test-2', handleDBCallback)
}
async function runMigrations() {
await execa('node', ['ace', 'migration:run'], { stdio: 'inherit' })
await execa('node', ['ace', 'migration:run', '-c', 'dl-test-1'], { stdio: 'inherit' })
await execa('node', ['ace', 'migration:run', '-c', 'dl-test-2'], { stdio: 'inherit' })
}
async function rollbackMigrations() {
await execa('node', ['ace', 'migration:rollback', '--batch=0'], { stdio: 'inherit' })
await execa('node', ['ace', 'migration:rollback', '-c', 'dl-test-1', '--batch=0'], {
stdio: 'inherit',
})
await execa('node', ['ace', 'migration:rollback', '-c', 'dl-test-2', '--batch=0'], {
stdio: 'inherit',
})
}
async function startHttpServer() {
const { Ignitor } = await import('@adonisjs/core/build/src/Ignitor')
process.env.PORT = String(await getPort())
await new Ignitor(__dirname).httpServer().start()
}
function getTestFiles() {
let userDefined = process.argv.slice(2)[0]
if (!userDefined) {
return 'test/**/*.spec.ts'
}
return `${userDefined.replace(/\.ts$|\.js$/, '')}.ts`
}
/**
* Configure test runner
*/
configure({
files: getTestFiles(),
before: [createTestDbs, runMigrations, startHttpServer],
after: [rollbackMigrations],
})
First of all, I am not entirely sure if this is a bug, but I'll describe what is happening:
I recently created a project with Adonis.js, created some models and wrote some tests. I followed this instructions to wrap each test on a DB transaction.
I noticed that most of the time, the tests passed, but often times some would fail with duplicated key
errors when trying to insert a record in the DB. I double, triple, quadruple checked the codes, and they seemed to be ok, so I went digging deeper.
This is what the bootstra.ts file looked like initially:
import { expect } from '@japa/expect'
import type { Config } from '@japa/runner'
import TestUtils from '@ioc:Adonis/Core/TestUtils'
import Database from '@ioc:Adonis/Lucid/Database'
import { assert, runFailedTests, specReporter, apiClient } from '@japa/preset-adonis'
export const plugins: Config['plugins'] = [assert(), runFailedTests(), apiClient(), expect()]
export const reporters: Config['reporters'] = [specReporter()]
export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
setup: [() => TestUtils.ace().loadCommands(), () => TestUtils.db().migrate()],
teardown: [],
}
export const configureSuite: Config['configureSuite'] = (suite) => {
suite.setup(() => TestUtils.httpServer().start())
suite.onGroup((group) => {
group.each.setup(async () => {
await Database.beginGlobalTransaction()
return () => Database.rollbackGlobalTransaction()
})
})
}
And the I change the configureSuite
const with a log and a throw:
export const configureSuite: Config['configureSuite'] = (suite) => {
suite.setup(() => TestUtils.httpServer().start())
suite.onGroup((group) => {
console.log(group.title)
group.each.setup(async () => {
throw new Error('This should crash and fail the tests (I suppose)')
await Database.beginGlobalTransaction()
return () => Database.rollbackGlobalTransaction()
})
})
}
As expected, the console.log
call did print all the test group titles. However, the throw
call did not seem to have any effect at all. The tests continued to be ran, most of them succeed, others fail like said before.
Then I went further and wrote two simple test cases:
import { test } from '@japa/runner'
import Message from 'App/Models/Message'
import MessageService from 'App/Services/Message'
import { MessageFactory } from 'Database/factories'
test.group('some group', () => {
test('first test that usually passes', async ({ expect }) => {
const message = await MessageFactory.merge({ someUniqueValue: 123 }).create()
await new MessageService().processSentMessage(message)
expect(message.sentAt).not.toBeNull()
})
test('second test that usually fails', async ({ expect }) => {
const oldMessages = await Message.all()
// I expected this to always log 'THERE ARE 0 MESSAGES'
// but it often logs 'THERE ARE 1 MESSAGE', I assume remains from the previous test
console.log(`THERE ARE ${oldMessages.length} MESSAGES: ${oldMessages.map(m => m.id)}`)
const message = await MessageFactory.merge({ someUniqueValue: 123 }).create()
await new MessageService().processDeliveredMessage(message)
expect(message.deliveredAt).not.toBeNull()
})
})
And just like written in the comment, very often the second test starts with non-empty table of Messages.
"@japa/expect": "^1.1.4",
"@japa/preset-adonis": "^1.0.15",
"@japa/runner": "^2.0.7",
β second test that usually fails
insert into "messages" ("created_at", "some_unique_value", "updated_at") values ($1, $2, $3) returning "id" - duplicate key value violates unique constraint "messages_some_unique_value_unique"
If this is not a bug from Japa itself, the only hypothesis I could come up with is something wrong the the async/await calls, but I'm not sure.
I only tested with groups.each.setup
but I believe the issue occurs with teardown
, timeout
or any other method from group.each
.
I hope I included enough info to help debug this, but let me know if there's anything else I can provide.
So let's imagine that the user defines several reporters :
configure({
reporters: [specReporter(), dotReporter()]
})
In this case, we would like to have the output of a single reporter. But to also be able to choose the output of another reporter in a different context. For example, the SpecReporter would be for local dev, and the DotReporter for the CI.
The first thing to do would be to define names for the reporters so that they can be selected later via a --reporter
argument. My suggestion is this:
// Instead of
export type ReporterContract = (runner: Runner<any>, emitter: Emitter) => void | Promise<void>;
// The reporter factory would return an object like this. Name and manager
export type ReporterContract = {
name: string // Would be 'dot', or 'spec', for the above example
handler: (runner: Runner<any>, emitter: Emitter) => void | Promise<void>
}
However, this would consist of a breaking change. Which is pretty annoying for a small feature like this. My other suggestion, so that it does not cause a breaking change :
type ReporterHandler = (runner: Runner<any>, emitter: Emitter) => void | Promise<void>
type ReporterContract =
| { name: string; handler: ReporterHandler }
| ReporterHandler
And in case, just the handler is defined, without any name, maybe we could just assign a random one. When a user tries to use only his reporter via the --reporters
argument, and it is not found, we could display an error like "Reporter not found. Make sure you define a name for it".
To activate reporters, what I suggest :
--reporters
which accepts a list of names of reporters. node bin/test.ts --reporters=dot,json,spec
or node bin/test.ts --reporters=dot
Now the thing that's a bit boring. If I go back to the configuration that I put at the top of the issue. If I run my tests with node bin/test.ts
without specifying any reporter, then both (dot and spec) will be enabled.
So always having to specify a reporter could be a bit of a pain.
What I propose here is to add an enabled
property in the contract of each reporter :
// The reporter factory would return an object like this. Name and manager
export type ReporterContract =
| {
name: string;
handler: ReporterHandler
enabled: boolean
}
| ReporterHandler
By default, spec and dot would be set to enabled = false
. Passing the name of the reporter via the flag would enable it. And if ever, when notifying the reporters in the runner, we realize that none of the reporters are enabled
(which means that no --reporters
argument has been passed) then we'd default to enabling the spec reporter.
I'm not really convinced by this solution, but it's the only one I could see
In closing, there's a question I've been asking myself:
Why allow multiple reporters? Will the user really need to run several reporters at the same time?
If this is not the case, what I would suggest is maybe something like this :
// Specifiy one reporter
configure({
reporter: 'dot'
})
// Specify custom reporter
configure({
reporter: './path/to/reporter.ts' // or '@org/reporter'
})
And then we would import, directly from the runner, the reporter. Exactly like pino does with the transporters for example: https://github.com/Julien-R44/pino-loki#as-module
( For example, when you want to use pino-pretty, it tries to import it on its own, and if it doesn't find it, we get a nice error that invites us to install it. )
Let me know what you think about it !
As of now we have only terminal reporting. It will be good if we implement HTML test report.
2.0.8
3.1.1
Given a test script like below, how should one best get the typings included for TestContext
properties assert
and expect
which are already declared in @japa/assert and @japa/expect.
import { configure, processCLIArgs, run } from '@japa/runner';
import { assert } from '@japa/assert'
import { expect } from '@japa/expect';
processCLIArgs(process.argv.splice(2));
configure({
files: ['tests/**/*.spec.ts'],
plugins: [assert(), expect()],
});
run();
That is, how does one remove the red squiggly line under assert
in the following test file:
import { test } from '@japa/runner';
import type { TestContext } from '@japa/core';
function sum(a: number, b: number) {
return a + b
}
test('add two numbers', ({ assert }: TestContext) => {
assert.equal(sum(2, 2), 4)
})
No response
2.2.2
Node.js versions 16.17.0 & 18.12.1
Hello!
I have an ESM project and I tried to integrate Japa to run tests. However, when I run this command
node --loader=ts-node/esm bin/test.ts
I get the following error:
Only URLs with a scheme in: file, data are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'
1 defer
node_modules/.pnpm/[email protected]_2ddbbb1508daf8c6199f587657236c9e/node_modules/ts-node/src/esm.ts:159
2 entrypointFallback
node_modules/.pnpm/[email protected]_2ddbbb1508daf8c6199f587657236c9e/node_modules/ts-node/src/esm.ts:168
3 anonymous
node_modules/.pnpm/[email protected]_2ddbbb1508daf8c6199f587657236c9e/node_modules/ts-node/src/esm.ts:202
node_modules/.pnpm/[email protected]_2ddbbb1508daf8c6199f587657236c9e/node_modules/ts-node/src/esm.ts:409
5 resolve
node_modules/.pnpm/[email protected]_2ddbbb1508daf8c6199f587657236c9e/node_modules/ts-node/src/esm.ts:197
Same thing with tsx.
This is my tsconfig.json
file:
{
"compilerOptions": {
"target": "ESNext",
"lib": [
"ESNext",
"DOM"
],
"module": "ESNext",
"moduleResolution": "Node",
"baseUrl": ".",
"typeRoots": [
"src/types"
],
"outDir": "./dist",
"isolatedModules": false,
"esModuleInterop": true,
"skipLibCheck": true
},
"exclude": ["node_modules", "dist"],
"ts-node": {
"esm": true,
"transpileOnly": true
}
}
I have a simple test file:
import { test } from "@japa/runner";
import parsePolicy from "../src/parse_policy.js";
const policy = {
"@context": "http://www.w3.org/ns/odrl.jsonld",
"@type": "Set",
uid: "http://example.com/policy:1010",
permission: [
{
target: "http://example.com/asset:9898.movie",
action: "use",
},
],
};
test.group("Policy parser", () => {
test("should parse ODRL policy", async ({ assert }) => {
const parsedPolicy = await parsePolicy(JSON.stringify(policy));
assert.lengthOf(parsedPolicy.permissions, 1);
});
});
Thank you!
No response
As soon as an assertion fails, test case also fails. This increases the feedback loop for the user, instead of finding out all failing assertions in one run you have to iterate over each assertion line to see the problem as whole on a test case.
Example:
test('should return 2 failures', async ({ assert }) => {
assert.ok(null)
assert.ok(0)
})
Expected: 2 assertions failed line 123 and 124.
Actual: Assertion Error: expected null to be truthy
(A pretty print pointing at line 123)
"@japa/preset-adonis": "^1.0.15",
"@japa/runner": "^2.0.7",
This is the default behavior at Rails.
Japa
seems not to support async
handler current and breaks with the following unexpected behaviours:
async
handler fails without any specific error,group.tap((test) => test.pin())
results in all tests running (not just the tests within the pinned
group).async
handler runs few random tests with the pinned tests still failing. "@japa/api-client": "^1.2.0",
"@japa/assert": "^1.3.4",
"@japa/preset-adonis": "^1.0.15",
"@japa/run-failed-tests": "^1.0.7",
"@japa/runner": "^2.0.7",
As seen below, the failed test was the only pinned test within a group with async
handler but few other random tests ran while the pinned test still failed.
unit / Pagination Service (tests/unit/pagination_service.spec.ts)
β should return same pagination values if they are valid (1ms)
β should use `1` as `page` value if not provided (0ms)
β should use `20` as `per_page` value if not provided (0ms)
β should use `50` as `per_page` value if provided value is greater `50` (0ms)
{"level":30,"time":1653300409042,"pid":27492,"hostname":"Ndianabasi-Mac.lan","name":"backend-v1","msg":"started server on 0.0.0.0:4444"}
functional / Authentication (tests/functional/auth.spec.ts)
β User login should be successful (130ms)
tests/functional/workspace_users/update_users.spec.ts
β A superadmin can create and associate a user in any workspace (108ms)
Example of what I am trying to achieve with async
group handler is generating a fake file only once for the all tests within a group:
test.group('Workspace Users | create', async (group) => {
group.each.setup(async () => {
await Database.beginGlobalTransaction()
return () => Database.rollbackGlobalTransaction()
})
const role = () => faker.helpers.arrayElement(['designer', 'admin', 'manager'])
const fakeAvatar = await file.generatePng('1mb')
test('A superadmin can create and associate a user in any workspace', async ({
assert,
client: apiClient,
route,
}) => {
...
const response = await apiClient
.post(route('WorkspaceUsersController.store', [workspace.id]))
.field('full_name', newUser.fullName)
.field('email', newUser.email)
.field('role', role())
.file('avatar', fakeAvatar.contents, { filename: fakeAvatar.name })
.loginAs(superadmin)
...
})
})
Does Japa have a watch mode function? I couldn't find anything about this in the documentation.
2.0.5
I am collecting links to articles, packages, videos, etc. related to Japa. If you have created anything for Japa, then comment on this issue. I will occasionally pick links from the comments and update the main issue
2.2.2
In VSCode the expect
variable on TextContext
is not defined as far as TS is concerned. Test works as expected in runtime.
It seems like when I have the bin/test.ts
open in a split pane next to my spec file it can resolve the type OK, but if I just have the spec file open it shows the error and obviously no autocompletion or anything.
Might be a VSCode specific issue, but I'd assume it should be able to pick up the correct typing since I haven't seen any special setup instructions. Even when trying to add it to something like japaTypes.ts
doesn't fix the issue, but also expect
does exist on TextContext
in that declaration.
I'm trying to setup Japa to run typescript tests with ts-node into an existing Adonis v5.6.2 project. Setting up a basic test and importing classes from npm modules works fine.
In my test I'm trying to test password hashing like the old Japa docs for Adonis. I would assume that the tsconfig.json files and presets will pull in the correct import paths, but that doesn't seem to be the case.
2.0.6
test.spec.ts
import { test } from '@japa/runner'
import User from 'App/Models/User';
test('ensure user password gets hashed during save', async ({assert}) => {
const user = new User()
user.email = "[email protected]"
user.password = "secret"
await user.save()
assert.notEqual(user.password, 'secret')
})
β― npm run test
> [project]@1.0.0 test
> node -r ts-node/register/transpile-only bin/test.ts
Cannot find module 'App/Models/User'
Require stack:
- /Users/[user]/[project]/tests/test.spec.ts
- /Users/[user]/[project]/bin/test.ts
at Function.Module._resolveFilename internal/modules/cjs/loader.js:902
Updating the import User to a relative import works for importing the User model class, but fails at importing '@IOC:Adonis/Core/Hash'
import { test } from '@japa/runner'
import User from '../app/Models/User';
test('ensure user password gets hashed during save', async ({assert}) => {
const user = new User()
user.email = "[email protected]"
user.password = "secret"
await user.save()
assert.notEqual(user.password, 'secret')
})
β― npm run test
> [project]@1.0.0 test
> node -r ts-node/register/transpile-only bin/test.ts
Cannot find module '@ioc:Adonis/Core/Hash'
Require stack:
- /Users/[user]/[project]/app/Models/User.ts
- /Users/[user]/[project]/tests/test.spec.ts
- /Users/[user]/[project]/bin/test.ts
at Function.Module._resolveFilename internal/modules/cjs/loader.js:902
This is not a bug, i believe it is a more a discussion than a bug.
When running an functional test in japa my "with" function is executed before my test setup function.
Let me illustrate my use case:
i have the following test configuration:
import 'reflect-metadata'
import sourceMapSupport from 'source-map-support'
import execa from 'execa'
import { assert } from '@japa/assert'
import { specReporter } from '@japa/spec-reporter'
import { processCliArgs, configure, run } from '@japa/runner'
import { join } from 'path'
import type { HttpServer } from '@adonisjs/core/build/src/Ignitor/HttpServer'
import { Ignitor } from '@adonisjs/core/build/src/Ignitor'
sourceMapSupport.install({ handleUncaughtExceptions: false })
async function setupServer() {
let server: HttpServer;
try {
server = new Ignitor(join(__dirname, '..')).httpServer()
await server.start()
} catch (error) {
console.log("Erro ao subir o servidor de testes", error)
}
return async () => await server.close()
}
async function initTestBaseState() {
const Database = (await import('@ioc:Adonis/Lucid/Database')).default;
const { initCacheBaseState, resetCache } = (await import('Database/samples/SamplesUtils'));
try {
await execa.node('ace', ['migration:fresh', '--seed'], { stdio: 'inherit' });
initCacheBaseState();
await Database.beginGlobalTransaction()
} catch (error) {
console.log("Erro ao rodar migration:fresh", error)
}
return async () => {
await Database.commitGlobalTransaction()
resetCache();
}
}
async function restoreTestBaseState() {
const Database = (await import('@ioc:Adonis/Lucid/Database')).default;
const { restoreCacheBaseState } = (await import('Database/samples/SamplesUtils'));
await Database.rollbackGlobalTransaction()
restoreCacheBaseState();
await Database.beginGlobalTransaction()
}
configure({
...processCliArgs(process.argv.slice(2)),
...{
suites: [
{
name: 'unit',
files: ['japa/unit/**/*.fixture.ts'],
},
{
name: 'acceptance',
files: ['japa/acceptance/**/*.fixture.ts'],
configure: (suite) => {
suite.setup(initTestBaseState)
suite.onTest(test => test.setup(restoreTestBaseState))
}
}
],
setup: [setupServer],
plugins: [assert()],
reporters: [specReporter()],
importer: (filePath) => import(filePath)
},
})
run()
The order here -> it runs my setupServer
function -> it runs my configureSuite
function where i set the setup function of my funcional suite with Γ¬nitTestBaseState
, right here i delete, migrate and seed my database and begin a global transaction that is going to be rolled back after each functional test -> after that i set the setup function of each test to rollback to the initial state of the migration
The problem is that my with
functions contains data that's inserted on the database. If the with
is executed before, i lose the data on the rollback of the setup function.
Do you belive that is a good idea to run setup
before with
?
2.0.3
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.