diff --git a/.github/workflows/test-and-release.yaml b/.github/workflows/test-and-release.yaml new file mode 100644 index 0000000..ccece6a --- /dev/null +++ b/.github/workflows/test-and-release.yaml @@ -0,0 +1,36 @@ +name: Test and Release + +on: push + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JSR_TOKEN: ${{ secrets.JSR_TOKEN }} + +permissions: + contents: write + issues: write + id-token: write + +jobs: + tests: + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: "22.x" + cache: "npm" + + - name: Install dependencies + run: npm ci --no-audit + + - name: Test + run: npm test + + - name: Semantic release + continue-on-error: true + run: | + npm install -D @sebbo2002/semantic-release-jsr + npx semantic-release diff --git a/package.json b/package.json index 0b4b8be..65f4c4c 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "type": "module", "main": "waitForIt.ts", "scripts": { - "test": "npm test" + "test": "node --test --experimental-transform-types ./*.test.ts" }, "dependencies": { "backoff": "2.5.0" @@ -25,5 +25,16 @@ "@types/backoff": "2.5.5", "prettier": "3.4.2" }, - "prettier": "@bifravst/prettier-config" + "prettier": "@bifravst/prettier-config", + "release": { + "branches": [ + "main" + ], + "remoteTags": true, + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@sebbo2002/semantic-release-jsr" + ] + } } diff --git a/waitForIt.test.ts b/waitForIt.test.ts new file mode 100644 index 0000000..b0f2434 --- /dev/null +++ b/waitForIt.test.ts @@ -0,0 +1,47 @@ +import assert from 'node:assert' +import { describe, it, mock } from 'node:test' +import { waitForIt } from './waitForIt.ts' + +describe('waitForIt()', () => { + it('returns the result of a successful promise', async () => { + const expectedResult = 'success' + const succeeding = mock.fn(() => Promise.resolve(expectedResult)) + + const result = await waitForIt(succeeding) + + assert.strictEqual(result, expectedResult) + assert.equal(succeeding.mock.calls.length, 1) + }) + + it('returns the error of a failing promise', async () => { + const expectedTries = 2 + const expectedError = new Error('failure') + const failing = mock.fn(() => Promise.reject(expectedError)) + + try { + await waitForIt(failing, expectedTries) + assert.fail('Expected waitForIt to throw an error') + } catch (error) { + assert.strictEqual(error, expectedError) + } + assert.equal(failing.mock.calls.length, expectedTries) + }) + + it('returns the result after failing twice and succeeding on the third try', async () => { + const expectedResult = 'success' + const expectedTries = 3 + let callCount = 0 + const fn = mock.fn(() => { + callCount++ + if (callCount < expectedTries) { + return Promise.reject(new Error('failure')) + } + return Promise.resolve(expectedResult) + }) + + const result = await waitForIt(fn, expectedTries) + + assert.strictEqual(result, expectedResult) + assert.equal(fn.mock.calls.length, expectedTries) + }) +})