diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d40deac..70e1a06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,25 +6,81 @@ on: pull_request: branches: [main] +env: + BUILD_ARTIFACT_NAME: build_artifact + jobs: build: - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest + outputs: + tarball: ${{ steps.tarball.outputs.filename }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + - run: npm ci + - run: npm run test:ci + - name: Make build tarball + id: tarball + run: echo "filename=$(npm pack | tail -1)" >> $GITHUB_OUTPUT + - name: Archive build dist + uses: actions/upload-artifact@v4 + with: + name: ${{ env.BUILD_ARTIFACT_NAME }} + path: ${{ steps.tarball.outputs.filename }} + packageTest: + needs: build strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [ - 16, - 18, - 20, - 21, - ] + os: + - ubuntu-latest + - windows-latest + - macos-latest + node-version: + - 16 + - 18 + - 20 + - 22 + - 23 + + runs-on: ${{ matrix.os }} + env: + BUILD_ARTIFACT_FILENAME: ${{ needs.build.outputs.tarball }} steps: - - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - - run: npm ci - - run: npm run test:ci + - name: Download the build artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.BUILD_ARTIFACT_NAME }} + + # Linux and macOS setup + - if: ${{ runner.os != 'Windows' }} + name: Integration test - setup (non-Windows) + working-directory: ./integration_tests/esm + run: | + npm install "../../$BUILD_ARTIFACT_FILENAME" --omit=dev + cd ../cjs + npm install "../../$BUILD_ARTIFACT_FILENAME" --omit=dev + + # Windows setup + - if: ${{ runner.os == 'Windows' }} + name: Integration test - setup (Windows) + working-directory: ./integration_tests/esm + run: | + npm install "../../$Env:BUILD_ARTIFACT_FILENAME" --omit=dev + cd ../cjs + npm install "../../$Env:BUILD_ARTIFACT_FILENAME" --omit=dev + + # Run test + - name: Integration test - module format + working-directory: ./integration_tests/esm + run: npm run test + - name: Integration test - commonjs format + working-directory: ./integration_tests/cjs + run: npm run test diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..92f279e --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v22 \ No newline at end of file diff --git a/integration_tests/cjs/index.js b/integration_tests/cjs/index.js new file mode 100644 index 0000000..a85c035 --- /dev/null +++ b/integration_tests/cjs/index.js @@ -0,0 +1,33 @@ +const assert = require('node:assert'); +// eslint-disable-next-line import/no-unresolved +const { newServer } = require('mock-xmlhttprequest'); + +function functionToTest() { + return new Promise((resolve, reject) => { + // eslint-disable-next-line no-undef + const xhr = new XMLHttpRequest(); + xhr.open('GET', '/my/url'); + xhr.onload = () => resolve(JSON.parse(xhr.response)); + xhr.onerror = () => reject(xhr.statusText); + xhr.send(); + }); +} + +const server = newServer({ + get: ['/my/url', { + headers: { 'Content-Type': 'application/json' }, + body: '{ "message": "Success!" }', + }], +}); + +async function integrationTest() { + try { + server.install(); + const result = await functionToTest(); + assert.strictEqual(result.message, 'Success!'); + } finally { + server.remove(); + } +} + +integrationTest(); diff --git a/integration_tests/cjs/package.json b/integration_tests/cjs/package.json new file mode 100644 index 0000000..7d6224b --- /dev/null +++ b/integration_tests/cjs/package.json @@ -0,0 +1,11 @@ +{ + "name": "mock-xmlhttprequest-integration-test-esm", + "description": "Integration test for XMLHttpRequest in a Node.js commonjs project", + "type": "commonjs", + "scripts": { + "test": "node index.js" + }, + "engines": { + "node": ">=16.0.0" + } +} diff --git a/integration_tests/esm/index.js b/integration_tests/esm/index.js new file mode 100644 index 0000000..1b0dfca --- /dev/null +++ b/integration_tests/esm/index.js @@ -0,0 +1,33 @@ +import assert from 'node:assert'; +// eslint-disable-next-line import/no-unresolved +import { newServer } from 'mock-xmlhttprequest'; + +function functionToTest() { + return new Promise((resolve, reject) => { + // eslint-disable-next-line no-undef + const xhr = new XMLHttpRequest(); + xhr.open('GET', '/my/url'); + xhr.onload = () => resolve(JSON.parse(xhr.response)); + xhr.onerror = () => reject(xhr.statusText); + xhr.send(); + }); +} + +const server = newServer({ + get: ['/my/url', { + headers: { 'Content-Type': 'application/json' }, + body: '{ "message": "Success!" }', + }], +}); + +async function integrationTest() { + try { + server.install(); + const result = await functionToTest(); + assert.strictEqual(result.message, 'Success!'); + } finally { + server.remove(); + } +} + +integrationTest(); diff --git a/integration_tests/esm/package.json b/integration_tests/esm/package.json new file mode 100644 index 0000000..575d06e --- /dev/null +++ b/integration_tests/esm/package.json @@ -0,0 +1,11 @@ +{ + "name": "mock-xmlhttprequest-integration-test-esm", + "description": "Integration test for XMLHttpRequest in a Node.js module project", + "type": "module", + "scripts": { + "test": "node index.js" + }, + "engines": { + "node": ">=16.0.0" + } +} diff --git a/package.json b/package.json index 821dce2..ef27767 100644 --- a/package.json +++ b/package.json @@ -69,5 +69,12 @@ }, "engines": { "node": ">=16.0.0" + }, + "devEngines": { + "runtime": { + "name": "node", + "version": ">=22.0.0", + "onFail": "error" + } } }