diff --git a/lib/test_helper.js b/lib/test_helper.js index 7d646d0f..a70e7043 100644 --- a/lib/test_helper.js +++ b/lib/test_helper.js @@ -80,7 +80,7 @@ testHelper.deleteIndices = async ( ) => { await testHelper.forEachIndex( esClient.deleteIndex ); }; -testHelper.insertIntoIndex = async ( index, type, statements ) => { +testHelper.insertIntoIndex = async ( index, statements ) => { await esClient.connection.bulk( { index: `test_${index}`, body: statements, @@ -88,6 +88,14 @@ testHelper.insertIntoIndex = async ( index, type, statements ) => { } ); }; +testHelper.deleteFromIndex = async ( index, id ) => { + await esClient.connection.delete( { + index: `test_${index}`, + id, + refresh: true + } ); +}; + testHelper.loadElasticsearchFixtures = async ( ) => { const fixtures = JSON.parse( fs.readFileSync( "schema/fixtures.js" ) ); await Promise.all( _.map( fixtures.elasticsearch, ( values, index ) => { @@ -97,7 +105,7 @@ testHelper.loadElasticsearchFixtures = async ( ) => { statements.push( { index: { _index: `test_${index}`, _id: v.id } } ); statements.push( v ); } ); - return testHelper.insertIntoIndex( index, type, statements ); + return testHelper.insertIntoIndex( index, statements ); } ) ); }; @@ -117,6 +125,37 @@ testHelper.loadPostgresqlFixtures = async ( ) => { } ) ); }; +testHelper.insertJSObjectsIntoPostgresTable = async ( table, objects ) => Promise.all( + _.map( objects, async object => { + const fields = _.keys( object ); + const interpolate = _.map( new Array( fields.length ), ( n, i ) => `$${( i + 1 )}` ); + const { rows } = await pgClient.query( + `INSERT INTO ${table} ("${fields.join( "\", \"" )}") VALUES (${interpolate.join( "," )}) RETURNING id`, + _.values( object ) + ); + return rows[0].id; + } ) +); + +testHelper.deleteIdsFromPostgresTable = async ( table, ids ) => { + await pgClient.query( `DELETE FROM ${table} WHERE id IN (${ids.join( "," )})` ); +}; + +testHelper.insertJSObjectsIntoESIndex = async ( index, objects ) => { + const objectIds = _.map( objects, object => object.id ); + const statements = []; + _.each( objects, obj => { + statements.push( { index: { _index: `test_${index}`, _id: obj.id } } ); + statements.push( obj ); + } ); + await testHelper.insertIntoIndex( index, statements ); + return objectIds; +}; + +testHelper.deleteIdsFromESIndex = async ( index, ids ) => { + await Promise.all( _.map( ids, async id => testHelper.deleteFromIndex( index, id ) ) ); +}; + testHelper.testInatJSPreload = async ( controller, endpoint, method, klass, done ) => { const endpointStub = sinon.stub( endpoint, method ).callsFake( ( ) => ( new Promise( resolve => { @@ -164,5 +203,9 @@ module.exports = { loadElasticsearchFixtures: testHelper.loadElasticsearchFixtures, loadPostgresqlFixtures: testHelper.loadPostgresqlFixtures, testInatJSPreload: testHelper.testInatJSPreload, - testInatJSNoPreload: testHelper.testInatJSNoPreload + testInatJSNoPreload: testHelper.testInatJSNoPreload, + insertJSObjectsIntoPostgresTable: testHelper.insertJSObjectsIntoPostgresTable, + deleteIdsFromPostgresTable: testHelper.deleteIdsFromPostgresTable, + insertJSObjectsIntoESIndex: testHelper.insertJSObjectsIntoESIndex, + deleteIdsFromESIndex: testHelper.deleteIdsFromESIndex }; diff --git a/test/integration/v1/observations.js b/test/integration/v1/observations.js index 7e03ad8a..370dc7b5 100644 --- a/test/integration/v1/observations.js +++ b/test/integration/v1/observations.js @@ -6,6 +6,7 @@ const nock = require( "nock" ); const fs = require( "fs" ); const jwt = require( "jsonwebtoken" ); const config = require( "../../../config" ); +const testHelper = require( "../../../lib/test_helper" ); const fixtures = JSON.parse( fs.readFileSync( "schema/fixtures.js" ) ); @@ -699,6 +700,39 @@ describe( "Observations", ( ) => { } ).expect( 200, done ); } ); + it( "filters by term_value_id for multiple values", async function ( ) { + const annotationES = { + id: 2025101003, + controlled_attribute_id: 7, + controlled_value_id: 8, + concatenated_attr_val: "7|8", + vote_score_short: 0 + }; + const observationES = { + id: 2025101004, + user: { + id: 2025101002 + }, + annotations: [ + annotationES + ] + }; + const observationESIds = await testHelper.insertJSObjectsIntoESIndex( "observations", [observationES] ); + const cleanUp = async () => { + await testHelper.deleteIdsFromESIndex( "observations", observationESIds ); + }; + + try { + await request( this.app ).get( "/v1/observations?term_id=7&term_value_id=8,9" ) + .expect( res => { + expect( res.body.results.length ).to.eq( 1 ); + expect( res.body.results.map( r => r.id ) ).to.contain( observationES.id ); + } ).expect( 200 ); + } finally { + await cleanUp(); + } + } ); + it( "filters by without_term_id", function ( done ) { request( this.app ).get( "/v1/observations?without_term_id=1&id=6,7,9" ) .expect( res => { diff --git a/test/integration/v1/users.js b/test/integration/v1/users.js index 91554ae2..057d007a 100644 --- a/test/integration/v1/users.js +++ b/test/integration/v1/users.js @@ -5,6 +5,7 @@ const request = require( "supertest" ); const nock = require( "nock" ); const fs = require( "fs" ); const config = require( "../../../config" ); +const testHelper = require( "../../../lib/test_helper" ); const fixtures = JSON.parse( fs.readFileSync( "schema/fixtures.js" ) ); @@ -247,6 +248,55 @@ describe( "Users", ( ) => { .expect( 200, done ); } ); + it( "returns monthly supporter = true even if user does not prefer to show the monthly badge", async function ( ) { + const userPG = { + id: 2025101011, + created_at: "2025-10-10 00:00:00", + updated_at: "2025-10-10 00:00:00", + last_active: "2025-10-10", + login: "20251011_monthly_supporter", + name: "Monthly Supporter", + site_id: 1, + donorbox_plan_status: "active", + donorbox_plan_type: "monthly" + }; + const userES = { + id: 2025101011, + login: "20251011_monthly_supporter", + suspended: false + }; + const preferencePG = { + id: 2025101013, + name: "prefers_monthly_supporter_badge", + owner_id: 2025101011, + owner_type: "User", + value: "f" + }; + const userPGIds = await testHelper.insertJSObjectsIntoPostgresTable( "users", [userPG] ); + const preferencePGIds = await testHelper.insertJSObjectsIntoPostgresTable( "preferences", [preferencePG] ); + const userESIds = await testHelper.insertJSObjectsIntoESIndex( "users", [userES] ); + const cleanUp = async () => { + await testHelper.deleteIdsFromPostgresTable( "users", userPGIds ); + await testHelper.deleteIdsFromPostgresTable( "preferences", preferencePGIds ); + await testHelper.deleteIdsFromESIndex( "users", userESIds ); + }; + + const token = jwt.sign( { user_id: 2025101011 }, + config.jwtSecret || "secret", + { algorithm: "HS512" } ); + try { + await request( this.app ).get( "/v1/users/me" ).set( "Authorization", token ) + .expect( res => { + expect( res.body.total_results ).to.eq( 1 ); + expect( res.body.results[0].monthly_supporter ).to.eq( true ); + } ) + .expect( "Content-Type", /json/ ) + .expect( 200 ); + } finally { + await cleanUp(); + } + } ); + _.each( [ "confirmation_sent_at", "confirmed_at",