Add experimental Bun test runner (#2353)

* Add experimental Bun test runner

* Add TypeScript export for Bun

* Clean up tests to prevent TypeScript build warnings

* Use Node.js 22 to run codegen

* Squash a couple TypeScript errors during tests

These are expected errors, to test edge cases for non-TS users

* Ignore Bun lockfile

* Drop unused index.ts

* Move unit test file list to tap config
This commit is contained in:
Josh Mock
2024-08-28 12:33:46 -05:00
committed by GitHub
parent 889fee2316
commit 9e08aaebe2
8 changed files with 155 additions and 123 deletions

184
.github/make.sh vendored
View File

@ -37,7 +37,7 @@ product="elastic/elasticsearch-js"
output_folder=".buildkite/output"
codegen_folder=".buildkite/output"
OUTPUT_DIR="$repo/${output_folder}"
NODE_JS_VERSION=18
NODE_JS_VERSION=22
WORKFLOW=${WORKFLOW-staging}
mkdir -p "$OUTPUT_DIR"
@ -46,84 +46,84 @@ echo -e "\033[34;1mINFO:\033[0m VERSION ${STACK_VERSION}\033[0m"
echo -e "\033[34;1mINFO:\033[0m OUTPUT_DIR ${OUTPUT_DIR}\033[0m"
case $CMD in
clean)
echo -e "\033[36;1mTARGET: clean workspace $output_folder\033[0m"
rm -rf "$output_folder"
echo -e "\033[32;1mdone.\033[0m"
exit 0
;;
assemble)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: assemble -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: assemble artifact $VERSION\033[0m"
TASK=release
TASK_ARGS=("$VERSION" "$output_folder")
;;
codegen)
if [ -v "$VERSION" ] || [[ -z "$VERSION" ]]; then
# fall back to branch name or `main` if no VERSION is set
branch_name=$(git rev-parse --abbrev-ref HEAD)
if [[ "$branch_name" =~ ^[0-9]+\.[0-9]+ ]]; then
echo -e "\033[36;1mTARGET: codegen -> No VERSION argument found, using branch name: \`$branch_name\`\033[0m"
VERSION="$branch_name"
else
echo -e "\033[36;1mTARGET: codegen -> No VERSION argument found, using \`main\`\033[0m"
VERSION="main"
fi
fi
if [ "$VERSION" = 'main' ]; then
echo -e "\033[36;1mTARGET: codegen API $VERSION\033[0m"
else
echo -e "\033[36;1mTARGET: codegen API v$VERSION\033[0m"
fi
clean)
echo -e "\033[36;1mTARGET: clean workspace $output_folder\033[0m"
rm -rf "$output_folder"
echo -e "\033[32;1mdone.\033[0m"
exit 0
;;
assemble)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: assemble -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: assemble artifact $VERSION\033[0m"
TASK=release
TASK_ARGS=("$VERSION" "$output_folder")
;;
codegen)
if [ -v "$VERSION" ] || [[ -z "$VERSION" ]]; then
# fall back to branch name or `main` if no VERSION is set
branch_name=$(git rev-parse --abbrev-ref HEAD)
if [[ "$branch_name" =~ ^[0-9]+\.[0-9]+ ]]; then
echo -e "\033[36;1mTARGET: codegen -> No VERSION argument found, using branch name: \`$branch_name\`\033[0m"
VERSION="$branch_name"
else
echo -e "\033[36;1mTARGET: codegen -> No VERSION argument found, using \`main\`\033[0m"
VERSION="main"
fi
fi
if [ "$VERSION" = 'main' ]; then
echo -e "\033[36;1mTARGET: codegen API $VERSION\033[0m"
else
echo -e "\033[36;1mTARGET: codegen API v$VERSION\033[0m"
fi
TASK=codegen
TASK_ARGS=("$VERSION")
;;
docsgen)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: docsgen -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: generate docs for $VERSION\033[0m"
TASK=codegen
TASK_ARGS=("$VERSION" "$codegen_folder")
;;
examplesgen)
echo -e "\033[36;1mTARGET: generate examples\033[0m"
TASK=codegen
TASK_ARGS=("$VERSION" "$codegen_folder")
;;
bump)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: bump -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: bump to version $VERSION\033[0m"
TASK=bump
TASK_ARGS=("$VERSION")
;;
bumpmatrix)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: bumpmatrix -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: bump stack in test matrix to version $VERSION\033[0m"
TASK=bumpmatrix
TASK_ARGS=("$VERSION")
;;
*)
echo -e "\n'$CMD' is not supported right now\n"
echo -e "\nUsage:"
echo -e "\t $0 release \$VERSION\n"
echo -e "\t $0 bump \$VERSION"
echo -e "\t $0 codegen \$VERSION"
exit 1
TASK=codegen
TASK_ARGS=("$VERSION")
;;
docsgen)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: docsgen -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: generate docs for $VERSION\033[0m"
TASK=codegen
TASK_ARGS=("$VERSION" "$codegen_folder")
;;
examplesgen)
echo -e "\033[36;1mTARGET: generate examples\033[0m"
TASK=codegen
TASK_ARGS=("$VERSION" "$codegen_folder")
;;
bump)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: bump -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: bump to version $VERSION\033[0m"
TASK=bump
TASK_ARGS=("$VERSION")
;;
bumpmatrix)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: bumpmatrix -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: bump stack in test matrix to version $VERSION\033[0m"
TASK=bumpmatrix
TASK_ARGS=("$VERSION")
;;
*)
echo -e "\n'$CMD' is not supported right now\n"
echo -e "\nUsage:"
echo -e "\t $0 release \$VERSION\n"
echo -e "\t $0 bump \$VERSION"
echo -e "\t $0 codegen \$VERSION"
exit 1
;;
esac
# ------------------------------------------------------- #
# Build Container
# ------------------------------------------------------- #
@ -179,36 +179,36 @@ fi
# ------------------------------------------------------- #
if [[ "$CMD" == "assemble" ]]; then
if compgen -G ".buildkite/output/*" > /dev/null; then
echo -e "\033[32;1mTARGET: successfully assembled client v$VERSION\033[0m"
else
echo -e "\033[31;1mTARGET: assemble failed, empty workspace!\033[0m"
exit 1
fi
if compgen -G ".buildkite/output/*" >/dev/null; then
echo -e "\033[32;1mTARGET: successfully assembled client v$VERSION\033[0m"
else
echo -e "\033[31;1mTARGET: assemble failed, empty workspace!\033[0m"
exit 1
fi
fi
if [[ "$CMD" == "bump" ]]; then
if [ -n "$(git status --porcelain)" ]; then
echo -e "\033[32;1mTARGET: successfully bumped client v$VERSION\033[0m"
else
echo -e "\033[31;1mTARGET: failed bumped client v$VERSION\033[0m"
if [ -n "$(git status --porcelain)" ]; then
echo -e "\033[32;1mTARGET: successfully bumped client v$VERSION\033[0m"
else
echo -e "\033[31;1mTARGET: failed bumped client v$VERSION\033[0m"
exit 1
fi
fi
if [[ "$CMD" == "codegen" ]]; then
if [ -n "$(git status --porcelain)" ]; then
echo -e "\033[32;1mTARGET: successfully generated client v$VERSION\033[0m"
else
echo -e "\033[31;1mTARGET: failed generating client v$VERSION\033[0m"
if [ -n "$(git status --porcelain)" ]; then
echo -e "\033[32;1mTARGET: successfully generated client v$VERSION\033[0m"
else
echo -e "\033[31;1mTARGET: failed generating client v$VERSION\033[0m"
exit 1
fi
fi
if [[ "$CMD" == "docsgen" ]]; then
echo "TODO"
echo "TODO"
fi
if [[ "$CMD" == "examplesgen" ]]; then
echo "TODO"
echo "TODO"
fi

View File

@ -73,6 +73,36 @@ jobs:
run: |
npm run license-checker
test-bun:
name: Test Bun
runs-on: ${{ matrix.os }}
needs: paths-filter
# only run if code relevant to unit tests was changed
if: needs.paths-filter.outputs.src-only == 'true'
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v4
- name: Use Bun
uses: oven-sh/setup-bun@v2
- name: Install
run: |
bun install
- name: Lint
run: |
bun run lint
- name: Unit test
run: |
bun run test:unit-bun
auto-approve:
name: Auto-approve
needs: [test, license]

1
.gitignore vendored
View File

@ -64,3 +64,4 @@ test/bundlers/parcel-test/.parcel-cache
lib
junit-output
bun.lockb

View File

@ -72,3 +72,4 @@ CODE_OF_CONDUCT.md
CONTRIBUTING.md
src
bun.lockb

View File

@ -9,11 +9,12 @@
"require": "./index.js"
},
"scripts": {
"test": "npm run build && npm run lint && tap test/unit/{*,**/*}.test.ts",
"test:unit": "npm run build && tap test/unit/{*,**/*}.test.ts",
"test:coverage-100": "npm run build && tap test/unit/{*,**/*}.test.ts --coverage --100",
"test:coverage-report": "npm run build && tap test/unit/{*,**/*}.test.ts --coverage && nyc report --reporter=text-lcov > coverage.lcov",
"test:coverage-ui": "npm run build && tap test/unit/{*,**/*}.test.ts --coverage --coverage-report=html",
"test": "npm run build && npm run lint && tap",
"test:unit": "npm run build && tap",
"test:unit-bun": "bun run build && bunx tap",
"test:coverage-100": "npm run build && tap --coverage --100",
"test:coverage-report": "npm run build && tap --coverage && nyc report --reporter=text-lcov > coverage.lcov",
"test:coverage-ui": "npm run build && tap --coverage --coverage-report=html",
"test:integration": "tsc && node test/integration/index.js",
"lint": "ts-standard src",
"lint:fix": "ts-standard --fix src",
@ -94,6 +95,7 @@
"jsx": false,
"flow": false,
"coverage": false,
"check-coverage": false
"check-coverage": false,
"files": "test/unit/{*,**/*}.test.ts"
}
}

View File

@ -205,7 +205,7 @@ test('With generic document', async t => {
}
const Connection = connection.buildMockConnection({
onRequest (opts) {
onRequest (_opts) {
return {
statusCode: 200,
body: {

View File

@ -24,7 +24,7 @@ import FakeTimers from '@sinonjs/fake-timers'
test('Basic', async t => {
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
body: {
responses: [{
@ -78,7 +78,7 @@ test('Multiple searches (inside async iterator)', t => {
t.plan(4)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
body: {
responses: [{
@ -161,7 +161,7 @@ test('Multiple searches (async iterator exits)', t => {
t.plan(4)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
body: {
responses: [{
@ -242,7 +242,7 @@ test('Multiple searches (async iterator exits)', t => {
test('Stop a msearch processor (promises)', async t => {
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return { body: {} }
}
})
@ -272,7 +272,7 @@ test('Bad header', t => {
t.plan(1)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return { body: {} }
}
})
@ -297,7 +297,7 @@ test('Bad body', t => {
t.plan(1)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return { body: {} }
}
})
@ -321,7 +321,7 @@ test('Bad body', t => {
test('Retry on 429', async t => {
let count = 0
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
if (count++ === 0) {
return {
body: {
@ -384,7 +384,7 @@ test('Retry on 429', async t => {
test('Single search errors', async t => {
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
body: {
responses: [{
@ -419,7 +419,7 @@ test('Entire msearch fails', t => {
t.plan(2)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
statusCode: 500,
body: {
@ -454,7 +454,7 @@ test('Resolves the msearch helper', t => {
t.plan(1)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return { body: {} }
}
})
@ -470,17 +470,17 @@ test('Resolves the msearch helper', t => {
m.then(
() => t.pass('called'),
e => t.fail('Should not fail')
_e => t.fail('Should not fail')
)
m.catch(e => t.fail('Should not fail'))
m.catch(_e => t.fail('Should not fail'))
})
test('Stop the msearch helper with an error', t => {
t.plan(3)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return { body: {} }
}
})
@ -511,7 +511,7 @@ test('Multiple searches (concurrency = 1)', t => {
t.plan(4)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
body: {
responses: [{
@ -587,7 +587,7 @@ test('Flush interval', t => {
t.teardown(() => clock.uninstall())
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
body: {
responses: [{
@ -640,7 +640,7 @@ test('Flush interval - early stop', t => {
t.plan(2)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
body: {
responses: [{
@ -684,7 +684,7 @@ test('Stop should resolve the helper', t => {
t.plan(1)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
body: {
responses: []
@ -709,7 +709,7 @@ test('Stop should resolve the helper (error)', t => {
t.plan(3)
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
return {
body: {
responses: []

View File

@ -196,7 +196,7 @@ test('Scroll search (retry throws and maxRetries)', async t => {
const expectedAttempts = maxRetries + 1
let count = 0
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
count += 1
return { body: {}, statusCode: 429 }
}
@ -217,8 +217,7 @@ test('Scroll search (retry throws and maxRetries)', async t => {
})
try {
// @ts-expect-error
for await (const result of scrollSearch) { // eslint-disable-line
for await (const _result of scrollSearch) { // eslint-disable-line
t.fail('we should not be here')
}
} catch (err: any) {
@ -344,7 +343,7 @@ test('Should not retry if maxRetries = 0', async t => {
const expectedAttempts = 1
let count = 0
const MockConnection = connection.buildMockConnection({
onRequest (params) {
onRequest (_params) {
count += 1
return { body: {}, statusCode: 429 }
}
@ -365,8 +364,7 @@ test('Should not retry if maxRetries = 0', async t => {
})
try {
// @ts-expect-error
for await (const result of scrollSearch) { // eslint-disable-line
for await (const _result of scrollSearch) { // eslint-disable-line
t.fail('we should not be here')
}
} catch (err: any) {