Files
cgm-remote-monitor/tests/uuid-handling.test.js
T
Ben WestandCopilot 22f325c132 fix(tests): add missing closing brace in uuid-handling.test.js
First describe block was missing its closing });

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 17:17:33 -07:00

518 lines
15 KiB
JavaScript

'use strict';
/**
* UUID_HANDLING Feature Flag Tests
*
* Tests for GET/DELETE by UUID using the `identifier` field lookup.
*
* @see docs/backlogs/uuid-identifier-lookup.md
* @see lib/server/env.js (env.uuidHandling)
* @see lib/server/query.js (updateIdQuery UUID detection)
*/
var request = require('supertest');
var should = require('should');
var language = require('../lib/language')();
var api = require('../lib/api/');
var api_secret_hash = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
// Test UUIDs
var TEST_UUID = '550e8400-e29b-41d4-a716-446655440000';
var TEST_UUID_2 = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
/**
* Clear module caches to allow env reloading
*/
function clearModuleCache() {
var modulesToClear = [
'../lib/server/env',
'../lib/server/query',
'../lib/server/treatments',
'../lib/server/entries',
'../lib/api/entries/',
'../lib/api/',
'../lib/middleware/',
'../lib/server/bootevent'
];
modulesToClear.forEach(function(mod) {
try {
delete require.cache[require.resolve(mod)];
} catch (e) {
// Module not yet loaded
}
});
}
describe('UUID_HANDLING=false (explicit)', function() {
var self = this;
this.timeout(10000);
before(function(done) {
// Explicitly set UUID_HANDLING OFF (default changed to true in 15.0.7)
process.env.UUID_HANDLING = 'false';
clearModuleCache();
process.env.API_SECRET = 'this is my long pass phrase';
self.env = require('../lib/server/env')();
self.env.settings.authDefaultRoles = 'readable';
self.env.settings.enable = ['careportal', 'api'];
// Verify flag is off
self.env.uuidHandling.should.equal(false);
self.wares = require('../lib/middleware/')(self.env);
self.app = require('express')();
self.app.enable('api');
require('../lib/server/bootevent')(self.env, language).boot(function booted(ctx) {
self.ctx = ctx;
self.ctx.ddata = require('../lib/data/ddata')();
self.ctx.ddata.lastUpdated = Date.now();
self.app.use('/api', api(self.env, ctx));
done();
});
});
afterEach(function(done) {
self.ctx.treatments.remove({ find: {} }, done);
});
it('UUID-OFF-001: GET by UUID returns empty (no crash)', function(done) {
// Insert treatment with identifier
self.ctx.treatments.create([{
eventType: 'Note',
notes: 'Test note',
identifier: TEST_UUID,
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// GET by UUID _id - should return empty since flag is off
request(self.app)
.get('/api/treatments?find[_id]=' + TEST_UUID)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
res.body.length.should.equal(0);
done();
});
});
});
it('UUID-OFF-002: DELETE by UUID deletes nothing (no crash)', function(done) {
// Insert treatment
self.ctx.treatments.create([{
eventType: 'Note',
notes: 'Test for delete',
identifier: TEST_UUID,
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// DELETE by UUID - should not crash, delete nothing
request(self.app)
.delete('/api/treatments/' + TEST_UUID)
.set('api-secret', api_secret_hash)
.expect(200)
.end(function(err) {
should.not.exist(err);
// Verify treatment still exists
self.ctx.treatments.list({}, function(err, results) {
should.not.exist(err);
results.length.should.equal(1);
done();
});
});
});
});
it('UUID-OFF-003: POST with UUID _id strips UUID, does not copy to identifier', function(done) {
// When UUID_HANDLING=false, UUID in _id is stripped but NOT preserved as identifier
self.ctx.treatments.create([{
_id: TEST_UUID,
eventType: 'Note',
notes: 'UUID stripped write test',
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// Treatment was created (no crash), but UUID was not preserved as identifier
self.ctx.treatments.list({}, function(err, results) {
should.not.exist(err);
results.length.should.equal(1);
// identifier should NOT be set from the UUID _id when flag is false
should.not.exist(results[0].identifier);
done();
});
});
});
});
describe('UUID_HANDLING=true', function() {
var self = this;
this.timeout(10000);
before(function(done) {
// Enable UUID_HANDLING
process.env.UUID_HANDLING = 'true';
clearModuleCache();
process.env.API_SECRET = 'this is my long pass phrase';
self.env = require('../lib/server/env')();
self.env.settings.authDefaultRoles = 'readable';
self.env.settings.enable = ['careportal', 'api'];
// Verify flag is on
self.env.uuidHandling.should.equal(true);
self.wares = require('../lib/middleware/')(self.env);
self.app = require('express')();
self.app.enable('api');
require('../lib/server/bootevent')(self.env, language).boot(function booted(ctx) {
self.ctx = ctx;
self.ctx.ddata = require('../lib/data/ddata')();
self.ctx.ddata.lastUpdated = Date.now();
self.app.use('/api', api(self.env, ctx));
done();
});
});
afterEach(function(done) {
self.ctx.treatments.remove({ find: {} }, done);
});
after(function() {
delete process.env.UUID_HANDLING;
});
it('UUID-ON-001: GET by UUID finds treatment via identifier', function(done) {
// Insert treatment with identifier field
self.ctx.treatments.create([{
eventType: 'Note',
notes: 'Found by UUID',
identifier: TEST_UUID,
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// GET by UUID _id - should redirect to identifier search
request(self.app)
.get('/api/treatments?find[_id]=' + TEST_UUID)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
res.body.length.should.equal(1);
res.body[0].notes.should.equal('Found by UUID');
res.body[0].identifier.should.equal(TEST_UUID);
done();
});
});
});
it('UUID-ON-002: DELETE by UUID removes treatment via identifier', function(done) {
// Insert treatment
self.ctx.treatments.create([{
eventType: 'Note',
notes: 'Will be deleted',
identifier: TEST_UUID,
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// DELETE by UUID
request(self.app)
.delete('/api/treatments/' + TEST_UUID)
.set('api-secret', api_secret_hash)
.expect(200)
.end(function(err) {
should.not.exist(err);
// Verify treatment is gone
self.ctx.treatments.list({}, function(err, results) {
should.not.exist(err);
results.length.should.equal(0);
done();
});
});
});
});
it('UUID-ON-003: ObjectId still works normally', function(done) {
var ObjectID = require('mongodb').ObjectId;
var testId = new ObjectID();
// Insert treatment with ObjectId
self.ctx.treatments.create([{
_id: testId,
eventType: 'Note',
notes: 'ObjectId test',
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// GET by ObjectId - should work normally
request(self.app)
.get('/api/treatments?find[_id]=' + testId.toString())
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
res.body.length.should.equal(1);
res.body[0].notes.should.equal('ObjectId test');
done();
});
});
});
it('UUID-ON-004: Non-matching UUID returns empty', function(done) {
// Insert with different identifier
self.ctx.treatments.create([{
eventType: 'Note',
notes: 'Different UUID',
identifier: TEST_UUID_2,
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// Search for non-existing UUID
request(self.app)
.get('/api/treatments?find[_id]=' + TEST_UUID)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
res.body.length.should.equal(0);
done();
});
});
});
it('UUID-ON-005: POST with UUID _id extracts UUID to identifier', function(done) {
// When UUID_HANDLING=true, UUID in _id is extracted to identifier
self.ctx.treatments.create([{
_id: TEST_UUID,
eventType: 'Note',
notes: 'UUID write test',
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// UUID should have been moved to identifier
self.ctx.treatments.list({}, function(err, results) {
should.not.exist(err);
results.length.should.equal(1);
// identifier should be set from the UUID _id
results[0].identifier.should.equal(TEST_UUID);
done();
});
});
});
});
// ============================================
// ============================================
// UUID Edge Case Tests
// ============================================
describe('UUID Edge Cases', function() {
var self = this;
this.timeout(10000);
before(function(done) {
process.env.UUID_HANDLING = 'true';
clearModuleCache();
process.env.API_SECRET = 'this is my long pass phrase';
self.env = require('../lib/server/env')();
self.env.settings.authDefaultRoles = 'readable';
self.env.settings.enable = ['careportal', 'api'];
self.wares = require('../lib/middleware/')(self.env);
self.app = require('express')();
self.app.enable('api');
require('../lib/server/bootevent')(self.env, language).boot(function booted(ctx) {
self.ctx = ctx;
self.ctx.ddata = require('../lib/data/ddata')();
self.ctx.ddata.lastUpdated = Date.now();
self.app.use('/api', api(self.env, ctx));
done();
});
});
afterEach(function(done) {
self.ctx.treatments.remove({ find: {} }, done);
});
after(function() {
delete process.env.UUID_HANDLING;
});
it('UUID-EDGE-001: 23-char hex (invalid ObjectId) returns empty', function(done) {
// 23 chars - one short of valid ObjectId
var invalidId = '507f1f77bcf86cd79943901';
request(self.app)
.get('/api/treatments?find[_id]=' + invalidId)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
res.body.length.should.equal(0);
done();
});
});
it('UUID-EDGE-002: 25-char hex (too long) returns empty', function(done) {
// 25 chars - one more than valid ObjectId
var invalidId = '507f1f77bcf86cd7994390112';
request(self.app)
.get('/api/treatments?find[_id]=' + invalidId)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
res.body.length.should.equal(0);
done();
});
});
it('UUID-EDGE-003: UUID without hyphens not recognized as UUID', function(done) {
// UUID without hyphens (32 hex chars)
var noHyphenUUID = '550e8400e29b41d4a716446655440000';
// Insert treatment with hyphenated UUID
self.ctx.treatments.create([{
eventType: 'Note',
notes: 'Hyphenated UUID',
identifier: TEST_UUID,
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// Search with non-hyphenated version - should not match
request(self.app)
.get('/api/treatments?find[_id]=' + noHyphenUUID)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
res.body.length.should.equal(0);
done();
});
});
});
it('UUID-EDGE-004: Empty _id query returns all with date filter', function(done) {
self.ctx.treatments.create([{
eventType: 'Note',
notes: 'Test note',
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// Empty _id - should not crash, returns based on other filters
request(self.app)
.get('/api/treatments?find[_id]=')
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
// May return results based on date filter
done();
});
});
});
it('UUID-EDGE-005: Multiple treatments same identifier - documents upsert behavior', function(done) {
// treatments.create uses upsert by identifier, so duplicates are merged
// This test documents the expected behavior
var now = new Date();
var later = new Date(now.getTime() + 1000);
self.ctx.treatments.create([
{ eventType: 'Note', notes: 'First', identifier: TEST_UUID, created_at: now.toISOString() }
], function(err) {
should.not.exist(err);
self.ctx.treatments.create([
{ eventType: 'Note', notes: 'Second', identifier: TEST_UUID, created_at: later.toISOString() }
], function(err2) {
should.not.exist(err2);
request(self.app)
.get('/api/treatments?find[_id]=' + TEST_UUID)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
// Due to upsert by identifier, only 1 treatment exists (updated)
res.body.length.should.equal(1);
// The second create updates the first
res.body[0].notes.should.equal('Second');
done();
});
});
});
});
it('UUID-EDGE-006: Uppercase UUID matches case-insensitively', function(done) {
var lowerUUID = TEST_UUID.toLowerCase();
var upperUUID = TEST_UUID.toUpperCase();
// Insert with lowercase
self.ctx.treatments.create([{
eventType: 'Note',
notes: 'Lowercase UUID',
identifier: lowerUUID,
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
// Query with uppercase - UUID regex is case insensitive
// but identifier field match depends on stored value
request(self.app)
.get('/api/treatments?find[_id]=' + upperUUID)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
// Documents current behavior - uppercase query searches by identifier
// which is case-sensitive in MongoDB
done();
});
});
});
it('UUID-EDGE-007: Valid ObjectId still works normally', function(done) {
var ObjectID = require('mongodb').ObjectId;
var testId = new ObjectID();
self.ctx.treatments.create([{
_id: testId,
eventType: 'Note',
notes: 'ObjectId test',
created_at: new Date().toISOString()
}], function(err) {
should.not.exist(err);
request(self.app)
.get('/api/treatments?find[_id]=' + testId.toString())
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.be.Array();
res.body.length.should.equal(1);
res.body[0].notes.should.equal('ObjectId test');
done();
});
});
});
});