Skip to content

Commit

Permalink
Merge pull request #111 from biomage-org/example-experiment-fields
Browse files Browse the repository at this point in the history
[BIOMAGE-2386] Example experiment fields
  • Loading branch information
kafkasl authored Feb 13, 2023
2 parents 5ec06ef + ee38012 commit 154a533
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 10 deletions.
27 changes: 25 additions & 2 deletions src/api.v2/model/Experiment.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,32 @@ class Experiment extends BasicModel {
return result;
}


async getExampleExperiments() {
return this.getAllExperiments(constants.PUBLIC_ACCESS_ID);
const fields = [
'id',
'name',
'description',
'publication_title',
'publication_url',
'data_source_title',
'data_source_url',
'species',
'cell_count',
];

const aliasedExperimentFields = fields.map((column) => `e.${column}`);

const result = await this.sql
.select(aliasedExperimentFields)
.min('s.sample_technology as sample_technology')
.count('s.id as sample_count') // Returns a BigInt type which is represented as string (parse?)
.from(tableNames.USER_ACCESS)
.join(`${tableNames.EXPERIMENT} as e`, 'e.id', `${tableNames.USER_ACCESS}.experiment_id`)
.join(`${tableNames.SAMPLE} as s`, 'e.id', 's.experiment_id')
.where('user_id', constants.PUBLIC_ACCESS_ID)
.groupBy('e.id');

return result;
}

async getExperimentData(experimentId) {
Expand Down
5 changes: 3 additions & 2 deletions src/specs/api.v2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/ExperimentsList"
$ref: "#/components/schemas/ExampleExperimentsList"
"400":
description: Bad Request
content:
Expand Down Expand Up @@ -681,7 +681,6 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/HTTPError"

"/experiments/{experimentId}/samples/{sampleId}":
patch:
summary: Patch sample
Expand Down Expand Up @@ -2150,6 +2149,8 @@ components:
$ref: ./models/experiment-bodies/ProcessingConfig.v2.yaml
ExperimentsList:
$ref: ./models/experiment-bodies/ExperimentsList.v2.yaml
ExampleExperimentsList:
$ref: ./models/experiment-bodies/ExampleExperimentsList.v2.yaml
CreateSamples:
$ref: ./models/samples-bodies/CreateSamples.v2.yaml
GetSamples:
Expand Down
52 changes: 52 additions & 0 deletions src/specs/models/experiment-bodies/ExampleExperimentsList.v2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
title: Get all example experiments
type: array
items:
type: object
properties:
id:
type: string
name:
type: string
description:
type: string
nullable: true
publicationTitle:
type: string
nullable: true
publicationUrl:
type: string
nullable: true
dataSourceTitle:
type: string
nullable: true
dataSourceUrl:
type: string
nullable: true
species:
type: string
nullable: true
cellCount:
type: string
nullable: true
sampleCount:
type: string
sampleTechnology:
type: string
nullable: true

required:
- id
- name
- description
- publicationTitle
- publicationUrl
- dataSourceTitle
- dataSourceUrl
- species
- cellCount
- sampleCount
- sampleTechnology

additionalProperties: false

additionalProperties: false
29 changes: 29 additions & 0 deletions src/sql/migrations/20230207141717_add_example_experiment_fields.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = async (knex) => {
await knex.schema.alterTable('experiment', (table) => {
table.string('publication_title').nullable();
table.string('publication_url').nullable();
table.string('data_source_title').nullable();
table.string('data_source_url').nullable();
table.string('species').nullable();
table.integer('cell_count').nullable();
});
};

/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = async (knex) => {
await knex.schema.alterTable('experiment', (table) => {
table.dropColumn('publication_title');
table.dropColumn('publication_url');
table.dropColumn('data_source_title');
table.dropColumn('data_source_url');
table.dropColumn('species');
table.dropColumn('cell_count');
});
};
2 changes: 2 additions & 0 deletions tests/api.v2/mocks/getMockSqlClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ module.exports = () => {
onConflict: jest.fn().mockReturnThis(),
merge: jest.fn().mockReturnThis(),
andWhereLike: jest.fn().mockReturnThis(),
min: jest.fn().mockReturnThis(),
count: jest.fn().mockReturnThis(),
ref: jest.fn(),
};

Expand Down
33 changes: 27 additions & 6 deletions tests/api.v2/model/Experiment.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jest.mock('../../../src/sql/helpers', () => ({

const Experiment = require('../../../src/api.v2/model/Experiment');
const constants = require('../../../src/utils/constants');
const tableNames = require('../../../src/api.v2/model/tableNames');

const mockExperimentId = 'mockExperimentId';
const mockSampleId = 'mockSampleId';
Expand Down Expand Up @@ -77,15 +78,35 @@ describe('model/Experiment', () => {
});

it('getExampleExperiments works correctly', async () => {
const expectedResult = { isMockResult: true };
const queryResult = 'result';

mockSqlClient.groupBy.mockReturnValueOnce(queryResult);

const getAllExperimentsSpy = jest.spyOn(Experiment.prototype, 'getAllExperiments')
.mockImplementationOnce(() => Promise.resolve(expectedResult));
const expectedResult = await new Experiment().getExampleExperiments();

const result = await new Experiment().getExampleExperiments('mockUserId');
expect(queryResult).toEqual(expectedResult);

expect(result).toBe(expectedResult);
expect(getAllExperimentsSpy).toHaveBeenCalledWith(constants.PUBLIC_ACCESS_ID);
expect(sqlClient.get).toHaveBeenCalled();
expect(mockSqlClient.select).toHaveBeenCalledWith(
[
'e.id',
'e.name',
'e.description',
'e.publication_title',
'e.publication_url',
'e.data_source_title',
'e.data_source_url',
'e.species',
'e.cell_count',
],
);
expect(mockSqlClient.min).toHaveBeenCalledWith('s.sample_technology as sample_technology');
expect(mockSqlClient.count).toHaveBeenCalledWith('s.id as sample_count');
expect(mockSqlClient.from).toHaveBeenCalledWith(tableNames.USER_ACCESS);
expect(mockSqlClient.join).toHaveBeenCalledWith(`${tableNames.EXPERIMENT} as e`, 'e.id', `${tableNames.USER_ACCESS}.experiment_id`);
expect(mockSqlClient.join).toHaveBeenCalledWith(`${tableNames.SAMPLE} as s`, 'e.id', 's.experiment_id');
expect(mockSqlClient.where).toHaveBeenCalledWith('user_id', constants.PUBLIC_ACCESS_ID);
expect(mockSqlClient.groupBy).toHaveBeenCalledWith('e.id');
});

it('getExperimentData works correctly', async () => {
Expand Down

0 comments on commit 154a533

Please sign in to comment.