diff --git a/jest.config.js b/jest.config.js index 35556f3..efd3d7e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,4 +4,9 @@ module.exports = { transform: { '^.+\\.(ts)$': 'ts-jest', }, + globals: { + 'ts-jest': { + isolatedModules: true, + }, + }, }; diff --git a/src/__tests__/checkParameters.spec.ts b/src/__tests__/checkParameters.spec.ts new file mode 100644 index 0000000..2073e46 --- /dev/null +++ b/src/__tests__/checkParameters.spec.ts @@ -0,0 +1,107 @@ +import Client from '../internal'; +import { inputTypes, outputTypes, genomicModalities } from '../internal/internal.config'; + +interface CheckParametersArguments { + inputType: string; + outputType: string; + // inputSet: string[]; + genomicModality: string; + pValue?: number; +} + +it('should not throw an error', () => { + const testObj: CheckParametersArguments = { + inputType: 'cell', + outputType: 'organ', + // inputSet: [], + genomicModality: 'fake', + }; + expect(() => Client.checkParameters(testObj)).not.toThrow(); +}); + +it('should throw an error when output type is not in output types', () => { + interface FakeCheckParametersArguments { + inputType: string; + outputType: string; + // inputSet: string[]; + genomicModality: string; + pValue?: number; + } + + const outputType: string = 'fake'; + const testObj: FakeCheckParametersArguments = { + inputType: 'cell', + outputType, + // inputSet: [], + genomicModality: 'fake', + }; + expect(() => Client.checkParameters(testObj)).toThrow(`${outputType} not in ${outputTypes}`); +}); + +it('should throw an error when input type does correspond to output type', () => { + const inputType: string = 'protein'; + const outputType: string = 'organ'; + const testObj: CheckParametersArguments = { + inputType, + outputType, + // inputSet: [], + genomicModality: 'fake', + }; + expect(() => Client.checkParameters(testObj)).toThrow(`${inputType} not in ${inputTypes[outputType]}`); +}); + +it('should not throw an error when input type is gene and output type is cell', () => { + const testObj: CheckParametersArguments = { + inputType: 'gene', + outputType: 'cell', + // inputSet: [], + genomicModality: 'rna', + }; + expect(() => Client.checkParameters(testObj)).not.toThrow(); +}); + +it('should throw an error when input type is gene and output type is cell and genomic modality is not rna or atac', () => { + const genomicModality: string = 'fake'; + const testObj: CheckParametersArguments = { + inputType: 'gene', + outputType: 'cell', + // inputSet: [], + genomicModality, + }; + expect(() => Client.checkParameters(testObj)).toThrow(`${genomicModality} not in ${genomicModalities}`); +}); + +it('should not throw an error when input type is gene and output type is organ and p value within bounds', () => { + const testObj: CheckParametersArguments = { + inputType: 'gene', + outputType: 'cell', + // inputSet: [], + genomicModality: 'atac', + pValue: 0.2, + }; + expect(() => Client.checkParameters(testObj)).not.toThrow(); +}); + +it('should throw an error when input type is gene and output type is cell and p value is less than 0', () => { + const pValue: number = -0.1; + const testObj: CheckParametersArguments = { + inputType: 'gene', + outputType: 'organ', + // inputSet: [], + genomicModality: 'atac', + pValue, + }; + expect(() => Client.checkParameters(testObj)).toThrow(`p_value ${pValue} should be in [0,1]`); +}); + +it('should throw an error when input type is cell and output type is gene and p value is greater than 0', () => { + const pValue: number = 1.2; + const testObj: CheckParametersArguments = { + inputType: 'organ', + outputType: 'gene', + // inputSet: [], + genomicModality: 'atac', + pValue, + }; + expect(() => Client.checkParameters(testObj)).toThrow(`p_value ${pValue} should be in [0,1]`); +}); diff --git a/src/__tests__/example.spec.ts b/src/__tests__/example.spec.ts deleted file mode 100644 index 076d588..0000000 --- a/src/__tests__/example.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import sum from '../example'; - -test('Dummy unit test', () => { - const actual: number = sum(1, 2); - expect(actual).toBe(3); -}); diff --git a/src/example.ts b/src/example.ts deleted file mode 100644 index 3cc090d..0000000 --- a/src/example.ts +++ /dev/null @@ -1,5 +0,0 @@ -const sum = (a: number, b: number) => { - return a + b; -}; - -export default sum; diff --git a/src/index.ts b/src/index.ts index 5091123..655bdbb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,4 @@ -// eslint-disable-next-line -export const greet = () => console.log('Hello, world!'); +import Client from './internal'; + +// eslint-disable-next-line import/prefer-default-export +export { Client }; diff --git a/src/internal/index.ts b/src/internal/index.ts new file mode 100644 index 0000000..8bcccec --- /dev/null +++ b/src/internal/index.ts @@ -0,0 +1,63 @@ +import { CheckParametersTypes } from './internal.types'; +import { outputTypes, inputTypes, genomicModalities } from './internal.config'; + +class Client { + baseUrl: string; + + constructor(baseUrl: string) { + // https://cells.dev.hubmapconsortium.org/api/' + this.baseUrl = baseUrl; + } + + static checkParameters({ + inputType, + outputType, + // inputSet, + genomicModality, + pValue = 0.05, + }: CheckParametersTypes): void { + if (!outputTypes.includes(outputType)) { + throw new Error(`${outputType} not in ${outputTypes}`); + } + + if (!inputTypes[outputType].includes(inputType)) { + throw new Error(`${inputType} not in ${inputTypes[outputType]}`); + } + + if (inputType === 'gene' && outputType === 'cell' && !genomicModalities.includes(genomicModality)) { + throw new Error(`${genomicModality} not in ${genomicModalities}`); + } + + if ( + (((inputType === 'organ' && outputType === 'gene') || (inputType === 'gene' && outputType === 'organ')) && + pValue < 0) || + pValue > 1 + ) { + throw new Error(`p_value ${pValue} should be in [0,1]`); + } + } + + /* + fillRequestObject() {} + + hubmapQuery() {} + + setIntersection() {} + + setUnion() {} + + setDifference() {} + + operation() {} + + checkDetailParameters() {} + + setCount() {} + + setListEvaluation() {} + + setDetailEvaluation() {} + */ +} + +export default Client; diff --git a/src/internal/internal.config.ts b/src/internal/internal.config.ts new file mode 100644 index 0000000..0abd1a4 --- /dev/null +++ b/src/internal/internal.config.ts @@ -0,0 +1,15 @@ +import { InputTypes } from './internal.types'; + +const outputTypes: string[] = ['cell', 'organ', 'gene', 'cluster']; + +const inputTypes: InputTypes = { + // Allowed input types vary depending on output type + cell: ['gene', 'organ', 'protein', 'dataset'], + organ: ['cell', 'gene'], + gene: ['organ', 'cluster'], + cluster: ['gene'], +}; + +const genomicModalities: string[] = ['rna', 'atac']; // Used for quantitative gene->cell queries + +export { outputTypes, inputTypes, genomicModalities }; diff --git a/src/internal/internal.types.ts b/src/internal/internal.types.ts new file mode 100644 index 0000000..d072c14 --- /dev/null +++ b/src/internal/internal.types.ts @@ -0,0 +1,16 @@ +interface InputTypes { + cell: string[]; + organ: string[]; + gene: string[]; + cluster: string[]; +} + +interface CheckParametersTypes { + inputType: string; + outputType: keyof InputTypes; + // inputSet: string[]; + genomicModality: string; + pValue?: number; +} + +export { InputTypes, CheckParametersTypes };