From ac588a0fadd156de27622e9dd09101e1bead5d25 Mon Sep 17 00:00:00 2001 From: James Sumners Date: Thu, 3 Aug 2023 10:18:50 -0400 Subject: [PATCH] Add integration test for issue #923 --- .github/workflows/integration.yml | 4 +- docker-compose.yml | 8 +- package.json | 2 +- test-integration/client/issue-923.test.js | 91 +++++++++++++++++++++++ 4 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 test-integration/client/issue-923.test.js diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 3e360d0..90b77b8 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -20,10 +20,12 @@ jobs: services: openldap: - image: ghcr.io/ldapjs/docker-test-openldap/openldap:latest + image: ghcr.io/ldapjs/docker-test-openldap/openldap:2023-03-18 ports: - 389:389 - 636:636 + options: > + --health-cmd "ldapsearch -Y EXTERNAL -Q -H ldapi:// -b ou=people,dc=planetexpress,dc=com -LLL '(cn=Turanga Leela)' cn" steps: - uses: actions/checkout@v3 diff --git a/docker-compose.yml b/docker-compose.yml index f11187d..056d338 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,10 @@ -version: '3' - services: openldap: - image: ghcr.io/ldapjs/docker-test-openldap/openldap:latest + image: ghcr.io/ldapjs/docker-test-openldap/openldap:2023-03-18 ports: - 389:389 - 636:636 + healthcheck: + start_period: 3s + test: > + /usr/bin/ldapsearch -Y EXTERNAL -Q -H ldapi:// -b ou=people,dc=planetexpress,dc=com -LLL '(cn=Turanga Leela)' cn 1>/dev/null diff --git a/package.json b/package.json index 7309b87..60c8cc9 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "test:cov:html": "tap --coverage-report=html -R terse", "test:watch": "tap -n -w --no-coverage-report -R terse", "test:integration": "tap --no-cov -R terse 'test-integration/**/*.test.js'", - "test:integration:local": "docker-compose up -d && npm run test:integration && docker-compose down", + "test:integration:local": "docker-compose up -d --wait && npm run test:integration ; docker-compose down", "lint": "eslint . --fix", "lint:ci": "eslint .", "docs": "node scripts/build-docs.js" diff --git a/test-integration/client/issue-923.test.js b/test-integration/client/issue-923.test.js new file mode 100644 index 0000000..7dde9ec --- /dev/null +++ b/test-integration/client/issue-923.test.js @@ -0,0 +1,91 @@ +'use strict' + +const tap = require('tap') +const ldapjs = require('../../lib') +const { DN } = require('@ldapjs/dn') +const Change = require('@ldapjs/change') + +const SCHEME = process.env.SCHEME || 'ldap' +const HOST = process.env.HOST || '127.0.0.1' +const PORT = process.env.PORT || 389 +const baseURL = `${SCHEME}://${HOST}:${PORT}` + +const client = ldapjs.createClient({ url: baseURL }) + +tap.teardown(() => { + client.unbind() +}) + +tap.test('modifies entry specified by dn string', t => { + t.plan(4) + + client.bind('cn=admin,dc=planetexpress,dc=com', 'GoodNewsEveryone', (err) => { + t.error(err, 'bind error') + }) + + const dn = 'cn=large10,ou=large_ou,dc=planetexpress,dc=com' + const change = new Change({ + operation: 'replace', + modification: { + type: 'givenName', + values: ['test'] + } + }) + + client.modify(dn, change, (err) => { + t.error(err, 'modify error') + validateChange({ t, expected: 'test', client }) + }) +}) + +tap.test('modifies entry specified by dn object', t => { + t.plan(4) + + client.bind('cn=admin,dc=planetexpress,dc=com', 'GoodNewsEveryone', (err) => { + t.error(err, 'bind error') + }) + + const dn = DN.fromString('cn=large10,ou=large_ou,dc=planetexpress,dc=com') + const change = new Change({ + operation: 'replace', + modification: { + type: 'givenName', + values: ['test2'] + } + }) + + client.modify(dn, change, (err) => { + t.error(err, 'modify error') + validateChange({ t, expected: 'test2', client }) + }) +}) + +function validateChange ({ t, expected, client }) { + const searchBase = 'ou=large_ou,dc=planetexpress,dc=com' + const searchOpts = { + filter: '(cn=large10)', + scope: 'subtree', + attributes: ['givenName'], + sizeLimit: 10, + timeLimit: 0 + } + + client.search(searchBase, searchOpts, (err, res) => { + t.error(err, 'search error') + + res.on('searchEntry', entry => { + t.equal( + entry.attributes.filter(a => a.type === 'givenName').pop().values.pop(), + expected + ) + }) + + res.on('error', err => { + t.error(err, 'search entry error') + }) + + res.on('end', () => { + t.end() + }) + }) +}