diff --git a/migrate-mongo-config.js.sample b/migrate-mongo-config.js.sample new file mode 100644 index 000000000..7f13e03db --- /dev/null +++ b/migrate-mongo-config.js.sample @@ -0,0 +1,36 @@ +// In this file you can configure migrate-mongo + +const config = { + mongodb: { + // TODO Change (or review) the url to your MongoDB: + url: "mongodb://", + + // TODO Change this to your database name: + databaseName: "", + + options: { + useNewUrlParser: true, // removes a deprecation warning when connecting + useUnifiedTopology: true, // removes a deprecating warning when connecting + // connectTimeoutMS: 3600000, // increase connection timeout to 1 hour + // socketTimeoutMS: 3600000, // increase socket timeout to 1 hour + } + }, + + // The migrations dir, can be an relative or absolute path. Only edit this when really necessary. + migrationsDir: "migrations", + + // The mongodb collection where the applied changes are stored. Only edit this when really necessary. + changelogCollectionName: "changelog", + + // The file extension to create migrations and search for in migration dir + migrationFileExtension: ".js", + + // Enable the algorithm to create a checksum of the file contents and use that in the comparison to determine + // if the file should be run. Requires that scripts are coded to be run multiple times. + useFileHash: false, + + // Don't change this, unless you know what you're doing + moduleSystem: 'commonjs', +}; + +module.exports = config; diff --git a/src/auth/strategies/ldap.strategy.ts b/src/auth/strategies/ldap.strategy.ts index 53b4bc8d7..8e2e1be8e 100644 --- a/src/auth/strategies/ldap.strategy.ts +++ b/src/auth/strategies/ldap.strategy.ts @@ -30,6 +30,7 @@ export class LdapStrategy extends PassportStrategy(Strategy, "ldap") { const userFilter: FilterQuery = { $or: [ { username: `ldap.${payload.displayName}` }, + { username: payload.displayName }, { email: payload.mail as string }, ], }; @@ -42,6 +43,7 @@ export class LdapStrategy extends PassportStrategy(Strategy, "ldap") { authStrategy: "ldap", }; const user = await this.usersService.create(createUser); + console.log("Created ldap user ", user?.username); if (!user) { throw new InternalServerErrorException( @@ -81,6 +83,7 @@ export class LdapStrategy extends PassportStrategy(Strategy, "ldap") { }; await this.usersService.createUserIdentity(createUserIdentity); + console.log("Created user identity for ldap user with id ", user._id); } const foundUser = await this.usersService.findOne(userFilter); @@ -111,6 +114,7 @@ export class LdapStrategy extends PassportStrategy(Strategy, "ldap") { }, user._id, ); + console.log("Updated user identity for ldap user with id ", user._id); } return user; diff --git a/src/auth/strategies/oidc.strategy.ts b/src/auth/strategies/oidc.strategy.ts index 332d958cf..f3eee9c6e 100644 --- a/src/auth/strategies/oidc.strategy.ts +++ b/src/auth/strategies/oidc.strategy.ts @@ -94,6 +94,7 @@ export class OidcStrategy extends PassportStrategy(Strategy, "oidc") { "Could not create User from OIDC response.", ); } + console.log("Created oidc user ", newUser.username); const createUserIdentity: CreateUserIdentityDto = { authStrategy: "oidc", @@ -105,6 +106,7 @@ export class OidcStrategy extends PassportStrategy(Strategy, "oidc") { }; await this.usersService.createUserIdentity(createUserIdentity); + console.log("Created user identity for oidc user with id ", newUser._id); user = newUser; } else { diff --git a/src/casl/casl-ability.factory.ts b/src/casl/casl-ability.factory.ts index 8f3a246a7..35cd2c9ee 100644 --- a/src/casl/casl-ability.factory.ts +++ b/src/casl/casl-ability.factory.ts @@ -91,6 +91,9 @@ export class CaslAbilityFactory { // Instrument permissions can(Action.Read, Instrument); + if (user.currentGroups.some((g) => adminGroups.includes(g))) { + can(Action.Manage, Instrument); + } can(Action.Manage, Job); @@ -140,6 +143,10 @@ export class CaslAbilityFactory { cannot(Action.Update, Datablock); can(Action.Delete, Datablock); can(Action.Delete, PublishedData); + // instruments + cannot(Action.Create, Instrument); + cannot(Action.Update, Instrument); + can(Action.Delete, Instrument); } if (user.currentGroups.includes(Role.GlobalAccess)) { can(Action.Read, "all"); diff --git a/src/common/utils.ts b/src/common/utils.ts index 1613e640d..e13aee269 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -6,6 +6,7 @@ import { Expression, FilterQuery, Model, PipelineStage } from "mongoose"; import { DatasetType } from "src/datasets/dataset-type.enum"; import { IAxiosError, + IFilters, ILimitsFilter, IScientificFilter, } from "./interfaces/common.interface"; @@ -680,3 +681,38 @@ export const parseBoolean = (v: unknown): boolean => { return false; } }; + +export const replaceLikeOperator = (filter: IFilters): IFilters => { + if (filter.where) { + filter.where = replaceLikeOperatorRecursive( + filter.where as Record, + ); + } + return filter; +}; + +const replaceLikeOperatorRecursive = ( + input: Record, +): Record => { + const output = {} as Record; + for (const k in input) { + if (k == "like" && typeof input[k] !== "object") { + // we have encountered a loopback operator like + output["$regex"] = input[k]; + } else if (k == "$or" || k == "$and" || k == "$in") { + output[k] = (input[k] as Array).map((v) => + typeof v === "string" + ? v + : replaceLikeOperatorRecursive(v as Record), + ); + } else if (typeof input[k] === "object") { + output[k] = replaceLikeOperatorRecursive( + input[k] as Record, + ); + } else { + output[k] = input[k]; + } + } + + return output; +}; diff --git a/src/datasets/datasets.controller.ts b/src/datasets/datasets.controller.ts index c469351b7..830d049fd 100644 --- a/src/datasets/datasets.controller.ts +++ b/src/datasets/datasets.controller.ts @@ -79,7 +79,11 @@ import { UpdateDerivedDatasetDto, } from "./dto/update-derived-dataset.dto"; import { CreateDatasetDatablockDto } from "src/datablocks/dto/create-dataset-datablock"; -import { filterDescription, filterExample } from "src/common/utils"; +import { + filterDescription, + filterExample, + replaceLikeOperator, +} from "src/common/utils"; import { TechniqueClass } from "./schemas/technique.schema"; import { RelationshipClass } from "./schemas/relationship.schema"; import { JWTUser } from "src/auth/interfaces/jwt-user.interface"; @@ -375,10 +379,12 @@ export class DatasetsController { @Headers() headers: Record, @Query(new FilterPipe()) queryFilter: { filter?: string }, ): Promise { - const mergedFilters = this.updateMergedFiltersForList( - request, - this.getFilters(headers, queryFilter), - ); + const mergedFilters = replaceLikeOperator( + this.updateMergedFiltersForList( + request, + this.getFilters(headers, queryFilter), + ) as Record, + ) as IFilters; const datasets = await this.datasetsService.findAll(mergedFilters); if (datasets && datasets.length > 0) { @@ -610,10 +616,12 @@ export class DatasetsController { @Headers() headers: Record, @Query(new FilterPipe()) queryFilter: { filter?: string }, ): Promise { - const mergedFilters = this.updateMergedFiltersForList( - request, - this.getFilters(headers, queryFilter), - ); + const mergedFilters = replaceLikeOperator( + this.updateMergedFiltersForList( + request, + this.getFilters(headers, queryFilter), + ) as Record, + ) as IFilters; const dataset = await this.datasetsService.findOne(mergedFilters); if (dataset) { @@ -675,10 +683,12 @@ export class DatasetsController { @Headers() headers: Record, @Query(new FilterPipe()) queryFilter: { filter?: string }, ): Promise<{ count: number }> { - const mergedFilters = this.updateMergedFiltersForList( - request, - this.getFilters(headers, queryFilter), - ); + const mergedFilters = replaceLikeOperator( + this.updateMergedFiltersForList( + request, + this.getFilters(headers, queryFilter), + ) as Record, + ) as IFilters; return this.datasetsService.count(mergedFilters); } diff --git a/src/instruments/dto/create-instrument.dto.ts b/src/instruments/dto/create-instrument.dto.ts index a48dd7e16..7f9b779dd 100644 --- a/src/instruments/dto/create-instrument.dto.ts +++ b/src/instruments/dto/create-instrument.dto.ts @@ -1,9 +1,21 @@ -import { ApiProperty } from "@nestjs/swagger"; +import { ApiProperty, ApiTags } from "@nestjs/swagger"; +import { IsObject, IsOptional, IsString } from "class-validator"; +@ApiTags("instruments") export class CreateInstrumentDto { - @ApiProperty({ type: String, required: true }) + @ApiProperty({ + type: String, + required: true, + }) + @IsString() readonly name: string; - @ApiProperty({ type: Object, required: false, default: {} }) + @ApiProperty({ + type: Object, + required: false, + default: {}, + }) + @IsOptional() + @IsObject() readonly customMetadata?: Record; } diff --git a/src/instruments/instruments.controller.ts b/src/instruments/instruments.controller.ts index addee5e1a..dd18aa3aa 100644 --- a/src/instruments/instruments.controller.ts +++ b/src/instruments/instruments.controller.ts @@ -13,7 +13,13 @@ import { import { InstrumentsService } from "./instruments.service"; import { CreateInstrumentDto } from "./dto/create-instrument.dto"; import { UpdateInstrumentDto } from "./dto/update-instrument.dto"; -import { ApiBearerAuth, ApiQuery, ApiTags } from "@nestjs/swagger"; +import { + ApiBearerAuth, + ApiOperation, + ApiQuery, + ApiResponse, + ApiTags, +} from "@nestjs/swagger"; import { PoliciesGuard } from "src/casl/guards/policies.guard"; import { CheckPolicies } from "src/casl/decorators/check-policies.decorator"; import { AppAbility } from "src/casl/casl-ability.factory"; @@ -21,6 +27,11 @@ import { Action } from "src/casl/action.enum"; import { Instrument, InstrumentDocument } from "./schemas/instrument.schema"; import { FormatPhysicalQuantitiesInterceptor } from "src/common/interceptors/format-physical-quantities.interceptor"; import { IFilters } from "src/common/interfaces/common.interface"; +import { + filterDescription, + filterExample, + replaceLikeOperator, +} from "src/common/utils"; @ApiBearerAuth() @ApiTags("instruments") @@ -51,16 +62,45 @@ export class InstrumentsController { required: false, }) async findAll(@Query("filter") filter?: string): Promise { - const instrumentFilter: IFilters = JSON.parse( - filter ?? "{}", + const instrumentFilter: IFilters = replaceLikeOperator( + JSON.parse(filter ?? "{}"), ); return this.instrumentsService.findAll(instrumentFilter); } + // GET /instrument/findOne + @UseGuards(PoliciesGuard) + @CheckPolicies((ability: AppAbility) => ability.can(Action.Read, Instrument)) + @Get("/findOne") + @ApiOperation({ + summary: "It returns the first instrument found.", + description: + "It returns the first instrument of the ones that matches the filter provided. The list returned can be modified by providing a filter.", + }) + @ApiQuery({ + name: "filter", + description: + "Database filters to apply when retrieving instruments\n" + + filterDescription, + required: false, + type: String, + example: filterExample, + }) + @ApiResponse({ + status: 200, + type: Instrument, + description: "Return the instrument requested", + }) + async findOne(@Query("filter") filter?: string): Promise { + const instrumentFilters = replaceLikeOperator(JSON.parse(filter ?? "{}")); + + return this.instrumentsService.findOne(instrumentFilters); + } + @UseGuards(PoliciesGuard) @CheckPolicies((ability: AppAbility) => ability.can(Action.Read, Instrument)) @Get(":id") - async findOne(@Param("id") pid: string): Promise { + async findById(@Param("id") pid: string): Promise { return this.instrumentsService.findOne({ pid }); } diff --git a/src/instruments/instruments.service.spec.ts b/src/instruments/instruments.service.spec.ts index e6de9c33c..782500c3d 100644 --- a/src/instruments/instruments.service.spec.ts +++ b/src/instruments/instruments.service.spec.ts @@ -9,7 +9,6 @@ const mockInstrument: Instrument = { pid: "testPid", name: "Test", customMetadata: {}, - datasets: [], }; describe("InstrumentsService", () => { diff --git a/src/instruments/instruments.service.ts b/src/instruments/instruments.service.ts index b985bcfe4..1f111022a 100644 --- a/src/instruments/instruments.service.ts +++ b/src/instruments/instruments.service.ts @@ -23,18 +23,25 @@ export class InstrumentsService { const whereFilter: FilterQuery = filter.where ?? {}; const { limit, skip, sort } = parseLimitFilters(filter.limits); - return this.instrumentModel + const instrumentPromise = this.instrumentModel .find(whereFilter) .limit(limit) .skip(skip) - .sort(sort) - .exec(); + .sort(sort); + + const instruments = await instrumentPromise.exec(); + + return instruments; } async findOne( filter: FilterQuery, ): Promise { - return this.instrumentModel.findOne(filter).exec(); + const whereFilter: FilterQuery = filter.where ?? {}; + const fieldsProjection: FilterQuery = + filter.fields ?? {}; + + return this.instrumentModel.findOne(whereFilter, fieldsProjection).exec(); } async update( diff --git a/src/instruments/schemas/instrument.schema.ts b/src/instruments/schemas/instrument.schema.ts index 833e3474d..25396923d 100644 --- a/src/instruments/schemas/instrument.schema.ts +++ b/src/instruments/schemas/instrument.schema.ts @@ -1,25 +1,23 @@ import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose"; -import { ApiProperty, getSchemaPath } from "@nestjs/swagger"; +import { ApiProperty } from "@nestjs/swagger"; import { Document } from "mongoose"; -import { DatasetClass } from "src/datasets/schemas/dataset.schema"; import { v4 as uuidv4 } from "uuid"; export type InstrumentDocument = Instrument & Document; @Schema({ collection: "Instrument", + minimize: false, + timestamps: true, toJSON: { getters: true, }, }) export class Instrument { - @Prop({ type: String }) - _id: string; - @ApiProperty({ type: String, default: function genUUID(): string { - return process.env.PID_PREFIX + uuidv4(); + return (process.env.PID_PREFIX ? process.env.PID_PREFIX : "") + uuidv4(); }, required: true, description: "PID of the instrument", @@ -29,17 +27,25 @@ export class Instrument { unique: true, required: true, default: function genUUID(): string { - return process.env.PID_PREFIX + uuidv4(); + return (process.env.PID_PREFIX ? process.env.PID_PREFIX : "") + uuidv4(); }, }) pid: string; + @Prop({ + type: String, + }) + _id: string; + @ApiProperty({ type: String, required: true, description: "The name of the instrument.", }) - @Prop({ type: String, required: true }) + @Prop({ + type: String, + required: true, + }) name: string; @ApiProperty({ @@ -48,12 +54,12 @@ export class Instrument { default: {}, description: "JSON object containing custom metadata", }) - @Prop({ type: Object, required: false, default: {} }) + @Prop({ + type: Object, + required: false, + default: {}, + }) customMetadata: Record; - - @ApiProperty({ type: "array", items: { $ref: getSchemaPath(DatasetClass) } }) - @Prop([DatasetClass]) - datasets: DatasetClass[]; } export const InstrumentSchema = SchemaFactory.createForClass(Instrument); diff --git a/test/DatasetFilter.js b/test/DatasetFilter.js new file mode 100644 index 000000000..dd0dc512a --- /dev/null +++ b/test/DatasetFilter.js @@ -0,0 +1,645 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +"use strict"; + +const utils = require("./LoginUtils"); +const { TestData } = require("./TestData"); +const sandbox = require("sinon").createSandbox(); + +let accessTokenIngestor = null, + accessTokenUser1 = null, + accessTokenUser2 = null, + accessTokenUser3 = null, + accessTokenArchiveManager = null; + +let datasetPid1 = null, + encodedDatasetPid1 = null, + datasetPid2 = null, + encodedDatasetPid2 = null, + datasetPid3 = null, + encodedDatasetPid3 = null, + datasetPid4 = null, + encodedDatasetPid4 = null; + + +const RawCorrect1 = { + ...TestData.RawCorrect, + datasetName: "This is the first correct test raw dataset", + description: "There was no ice cream in the freezer, nor did they have money to go to the store. Part of the first two datasets", + isPublished: true, + ownerGroup: "group1", + accessGroups: ["group5"], +}; + +const RawCorrect2 = { + ...TestData.RawCorrect, + datasetName: "This is the second correct test raw dataset", + description: "There was no telling what thoughts would come from the machine. Part of the first two datasets", + isPublished: false, + ownerGroup: "group2", + accessGroups: ["group6"], +}; + +const RawCorrect3 = { + ...TestData.RawCorrect, + datasetName: "This is the third correct test raw dataset", + description: "The opportunity of a lifetime passed before him as he tried to decide between a cone or a cup. Last and third dataset", + isPublished: false, + ownerGroup: "group3", + accessGroups: ["group6"], +}; + +const RawCorrect4 = { + ...TestData.RawCorrect, + datasetName: "This is the fourth correct test dataset, and it is raw", + description: "After coating myself in vegetable oil I found my success rate skyrocketed", + isPublished: false, + ownerGroup: "group4", + accessGroups: ["group6"], +}; + +describe("DatasetFilter: Test retrieving datasets using filtering capabilities", () => { + beforeEach((done) => { + utils.getToken( + appUrl, + { + username: "ingestor", + password: "aman", + }, + (tokenVal) => { + accessTokenIngestor = tokenVal; + utils.getToken( + appUrl, + { + username: "user1", + password: "a609316768619f154ef58db4d847b75e", + }, + (tokenVal) => { + accessTokenUser1 = tokenVal; + utils.getToken( + appUrl, + { + username: "user2", + password: "f522d1d715970073a6413474ca0e0f63", + }, + (tokenVal) => { + accessTokenUser2 = tokenVal; + utils.getToken( + appUrl, + { + username: "user3", + password: "70dc489e8ee823ae815e18d664424df2", + }, + (tokenVal) => { + accessTokenUser3 = tokenVal; + utils.getToken( + appUrl, + { + username: "archiveManager", + password: "aman", + }, + (tokenVal) => { + accessTokenArchiveManager = tokenVal; + done(); + }, + ); + }, + ); + }, + ); + }, + ); + }, + ); + }); + + afterEach((done) => { + sandbox.restore(); + done(); + }); + + it("adds dataset 1", async () => { + return request(appUrl) + .post("/api/v3/Datasets") + .send(RawCorrect1) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .expect(200) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("ownerGroup").and.equal(RawCorrect1.ownerGroup); + res.body.should.have.property("type").and.equal(RawCorrect1.type); + res.body.should.have.property("isPublished").and.equal(RawCorrect1.isPublished); + res.body.should.have.property("pid").and.be.string; + datasetPid1 = res.body["pid"]; + encodedDatasetPid1 = encodeURIComponent(datasetPid1); + }); + }); + + it("adds dataset 2", async () => { + return request(appUrl) + .post("/api/v3/Datasets") + .send(RawCorrect2) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .expect(200) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("ownerGroup").and.equal(RawCorrect2.ownerGroup); + res.body.should.have.property("type").and.equal(RawCorrect2.type); + res.body.should.have.property("isPublished").and.equal(RawCorrect2.isPublished); + res.body.should.have.property("pid").and.be.string; + datasetPid2 = res.body["pid"]; + encodedDatasetPid2 = encodeURIComponent(datasetPid2); + }); + }); + + it("adds dataset 3", async () => { + return request(appUrl) + .post("/api/v3/Datasets") + .send(RawCorrect3) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .expect(200) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("ownerGroup").and.equal(RawCorrect3.ownerGroup); + res.body.should.have.property("type").and.equal(RawCorrect3.type); + res.body.should.have.property("isPublished").and.equal(RawCorrect3.isPublished); + res.body.should.have.property("pid").and.be.string; + datasetPid3 = res.body["pid"]; + encodedDatasetPid3 = encodeURIComponent(datasetPid3); + }); + }); + + it("adds dataset 4", async () => { + return request(appUrl) + .post("/api/v3/Datasets") + .send(RawCorrect4) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .expect(200) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("ownerGroup").and.equal(RawCorrect4.ownerGroup); + res.body.should.have.property("type").and.equal(RawCorrect4.type); + res.body.should.have.property("isPublished").and.equal(RawCorrect4.isPublished); + res.body.should.have.property("pid").and.be.string; + datasetPid4 = res.body["pid"]; + encodedDatasetPid4 = encodeURIComponent(datasetPid4); + }); + }); + + it("retrieve single dataset by its name", async () => { + const query = { where: { datasetName: RawCorrect1.datasetName } }; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(1); + res.body[0]["pid"].should.be.equal(datasetPid1); + }); + }); + + it("retrieve datasets with \"correct test raw\" in dataset name using loopback style \"like\" operator", async () => { + const query = { where: { datasetName: { like: "correct test raw" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(3); + }); + }); + + it("count how many datasets with \"correct test raw\" in dataset name using loopback style \"like\" operator", async () => { + const query = { where: { datasetName: { like: "correct test raw" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(3); + }); + }); + + it("retrieve one dataset with \"correct test raw\" in dataset name using loopback style \"like\" operator", async () => { + const query = { where: { datasetName: { like: "correct test raw" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.oneOf([datasetPid1, datasetPid2, datasetPid3]); + }); + }); + + it("retrieve datasets with \"correct test raw\" in dataset name using mongo regex operator", async () => { + const query = { where: { datasetName: { "$regex": "correct test raw" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(3); + }); + }); + + it("count how many datasets with \"correct test raw\" in dataset name using mongo regex operator", async () => { + const query = { where: { datasetName: { "$regex": "correct test raw" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(3); + }); + }); + + it("retrieve one datasets with \"correct test raw\" in dataset name using mongo regex operator", async () => { + const query = { where: { datasetName: { "$regex": "correct test raw" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.oneOf([datasetPid1, datasetPid2, datasetPid3]); + }); + }); + + + it("retrieve datasets with \"third correct\" in dataset name using loopback style \"like\" operator", async () => { + const query = { where: { datasetName: { like: "third correct" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(1); + res.body[0]["pid"].should.be.equal(datasetPid3); + }); + }); + + it("retrieve one dataset with \"third correct\" in dataset name using loopback style \"like\" operator", async () => { + const query = { where: { datasetName: { like: "third correct" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.equal(datasetPid3); + }); + }); + + it("count how many datasets with \"third correct\" in dataset name using loopback style \"like\" operator", async () => { + const query = { where: { datasetName: { like: "third correct" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(1); + }); + }); + + it("retrieve datasets with \"third correct\" in dataset name using mongo \"regex\" operator", async () => { + const query = { where: { datasetName: { "$regex": "third correct" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(1); + res.body[0]["pid"].should.be.equal(datasetPid3); + }); + }); + + it("retrieve one dataset with \"third correct\" in dataset name using mongo \"regex\" operator", async () => { + const query = { where: { datasetName: { "$regex": "third correct" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.equal(datasetPid3); + }); + }); + + it("count how many datasets with \"third correct\" in dataset name using mongo \"regex\" operator", async () => { + const query = { where: { datasetName: { "$regex": "third correct" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(1); + }); + }); + + it("retrieve datasets with \"Part of the first two dataset\" in description using loopback style \"like\" operator", async () => { + const query = { where: { description: { like: "Part of the first two datasets" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(2); + res.body[0]["pid"].should.be.oneOf([datasetPid1, datasetPid2]); + res.body[1]["pid"].should.be.oneOf([datasetPid1, datasetPid2]); + }); + }); + + it("retrieve one dataset with \"Part of the first two dataset\" in description using loopback style \"like\" operator", async () => { + const query = { where: { description: { like: "Part of the first two datasets" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.oneOf([datasetPid1, datasetPid2]); + }); + }); + + it("count how many datasets with \"Part of the first two dataset\" in description using loopback style \"like\" operator", async () => { + const query = { where: { description: { like: "Part of the first two datasets" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(2); + }); + }); + + it("retrieve datasets with \"Part of the first two dataset\" in description using \"regex\" operator", async () => { + const query = { where: { description: { "$regex": "Part of the first two datasets" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(2); + res.body[0]["pid"].should.be.oneOf([datasetPid1, datasetPid2]); + res.body[1]["pid"].should.be.oneOf([datasetPid1, datasetPid2]); + }); + }); + + it("retrieve one dataset with \"Part of the first two dataset\" in description using mongo \"regex\" operator", async () => { + const query = { where: { description: { "$regex": "Part of the first two datasets" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.oneOf([datasetPid1, datasetPid2]); + }); + }); + + it("count how many datasets with \"Part of the first two dataset\" in description using mongo \"regex\" operator", async () => { + const query = { where: { description: { "$regex": "Part of the first two datasets" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(2); + }); + }); + + it("retrieve datasets with \"lifetime passed\" in description using loopback style \"like\" operator", async () => { + const query = { where: { description: { like: "lifetime passed" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(1); + res.body[0]["pid"].should.be.equal(datasetPid3); + }); + }); + + it("retrieve one dataset with \"lifetime passed\" in description using loopback style \"like\" operator", async () => { + const query = { where: { description: { like: "lifetime passed" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.equal(datasetPid3); + }); + }); + + it("count how many datasets with \"lifetime passed\" in description using loopback style \"like\" operator", async () => { + const query = { where: { description: { like: "lifetime passed" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(1); + }); + }); + + it("retrieve datasets with \"lifetime passed\" in description using \"regex\" operator", async () => { + const query = { where: { description: { "$regex": "lifetime passed" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(1); + res.body[0]["pid"].should.be.equal(datasetPid3); + }); + }); + + it("retrieve one dataset with \"lifetime passed\" in description using \"regex\" operator", async () => { + const query = { where: { description: { "$regex": "lifetime passed" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.equal(datasetPid3); + }); + }); + + it("count how many datasets with \"lifetime passed\" in description using \"regex\" operator", async () => { + const query = { where: { description: { "$regex": "lifetime passed" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(1); + }); + }); + + it("retrieve datasets with \"second\" or \"third\" together with \"dataset\" in description using \"regex\" operator", async () => { + const query = { where: { datasetName: { "$regex": "(second|third).*dataset" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(2); + res.body[0]["pid"].should.be.oneOf([datasetPid2, datasetPid3]); + res.body[1]["pid"].should.be.oneOf([datasetPid2, datasetPid3]); + }); + }); + + it("retrieve one dataset with \"second\" or \"third\" together with \"dataset\" in description using \"regex\" operator", async () => { + const query = { where: { datasetName: { "$regex": "(second|third).*dataset" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.oneOf([datasetPid2, datasetPid3]); + }); + }); + + it("count how many datasets with \"second\" or \"third\" together with \"dataset\" in description using \"regex\" operator", async () => { + const query = { where: { datasetName: { "$regex": "(second|third).*dataset" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(2); + }); + }); + + it("retrieve datasets with \"cream\" and \"money\" or \"opportunity\" and \"decide\" in description using \"regex\" operator", async () => { + const query = { where: { description: { "$regex": "(cream.*money|opportunity.*decide)" }}}; + return request(appUrl) + .get("/api/v3/Datasets") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(2); + res.body[0]["pid"].should.be.oneOf([datasetPid1, datasetPid3]); + res.body[1]["pid"].should.be.oneOf([datasetPid1, datasetPid3]); + }); + }); + + it("retrieve one dataset with \"cream\" and \"money\" or \"opportunity\" and \"decide\" in description using \"regex\" operator", async () => { + const query = { where: { description: { "$regex": "(cream.*money|opportunity.*decide)" }}}; + return request(appUrl) + .get("/api/v3/Datasets/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.oneOf([datasetPid1, datasetPid3]); + }); + }); + + it("count how many datasets with \"cream\" and \"money\" or \"opportunity\" and \"decide\" in description using \"regex\" operator", async () => { + const query = { where: { description: { "$regex": "(cream.*money|opportunity.*decide)" }}}; + return request(appUrl) + .get("/api/v3/Datasets/count") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["count"].should.be.equal(2); + }); + }); + + it("should delete dataset 1", async () => { + return request(appUrl) + .delete("/api/v3/datasets/" + datasetPid1) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) + .expect(200) + .expect("Content-Type", /json/); + }); + + it("should delete dataset 2", async () => { + return request(appUrl) + .delete("/api/v3/datasets/" + datasetPid2) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) + .expect(200) + .expect("Content-Type", /json/); + }); + + it("should delete dataset 3", async () => { + return request(appUrl) + .delete("/api/v3/datasets/" + datasetPid3) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) + .expect(200) + .expect("Content-Type", /json/); + }); + + it("should delete dataset 4", async () => { + return request(appUrl) + .delete("/api/v3/datasets/" + datasetPid4) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) + .expect(200) + .expect("Content-Type", /json/); + }); + +}); diff --git a/test/Instrument.js b/test/Instrument.js new file mode 100644 index 000000000..eee2bb44a --- /dev/null +++ b/test/Instrument.js @@ -0,0 +1,115 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +"use strict"; + +const utils = require("./LoginUtils"); +const { TestData } = require("./TestData"); + +let accessToken = null, + accessTokenArchiveManager = null, + instrumentId = null; + +const newName="ESS2.5"; + +describe("Instrument: Instrument management", () => { + beforeEach((done) => { + utils.getToken( + appUrl, + { + username: "ingestor", + password: "aman", + }, + (tokenVal) => { + accessToken = tokenVal; + utils.getToken( + appUrl, + { + username: "archiveManager", + password: "aman", + }, + (tokenVal) => { + accessTokenArchiveManager = tokenVal; + done(); + }, + ); + }, + ); + }); + + it("adds new instrument", async () => { + return request(appUrl) + .post("/api/v3/Instruments") + .send(TestData.InstrumentCorrect) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessToken}` }) + .expect(201) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("name").and.be.equal(TestData.InstrumentCorrect.name); + res.body.should.have.property("pid").and.be.string; + instrumentId = res.body["pid"]; + }); + }); + + it("should fetch this new instrument", async () => { + return request(appUrl) + .get("/api/v3/Instruments/" + instrumentId) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessToken}` }) + .expect(200) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("name").and.be.equal(TestData.InstrumentCorrect.name); + res.body.should.have.property("pid").and.be.equal(instrumentId); + }); + }); + + it("should fetch all instruments", async () => { + return request(appUrl) + .get("/api/v3/Instruments") + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessToken}` }) + .expect(200) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.length(1); + res.body[0].should.have.property("name").and.be.equal(TestData.InstrumentCorrect.name); + res.body[0].should.have.property("pid").and.be.equal(instrumentId); + }); + }); + + it("should update the instrument name", async () => { + return request(appUrl) + .patch("/api/v3/Instruments/" + instrumentId) + .send({ name: newName }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessToken}` }) + .expect(200) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("name").and.be.equal(newName); + res.body.should.have.property("pid").and.be.equal(instrumentId); + }); + }); + + it("should fetch this same instrument", async () => { + return request(appUrl) + .get("/api/v3/Instruments/" + instrumentId) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessToken}` }) + .expect(200) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("name").and.be.equal(newName); + res.body.should.have.property("pid").and.be.equal(instrumentId); + }); + }); + + it("should delete this instrument", async () => { + return request(appUrl) + .delete("/api/v3/Instruments/" + instrumentId) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) + .expect(200) + .expect("Content-Type", /json/); + }); +}); diff --git a/test/InstrumentsFilter.js b/test/InstrumentsFilter.js new file mode 100644 index 000000000..5c6d700eb --- /dev/null +++ b/test/InstrumentsFilter.js @@ -0,0 +1,414 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +"use strict"; + +const utils = require("./LoginUtils"); +const { TestData } = require("./TestData"); +const sandbox = require("sinon").createSandbox(); + +let accessTokenIngestor = null, + accessTokenUser1 = null, + accessTokenUser2 = null, + accessTokenUser3 = null, + accessTokenArchiveManager = null; + +let instrumentPid1 = null, + encodedInstrumentPid1 = null, + instrumentPid2 = null, + encodedInstrumentPid2 = null, + instrumentPid3 = null, + encodedInstrumentPid3 = null, + instrumentPid4 = null, + encodedInstrumentPid4 = null; + + +const InstrumentCorrect1 = { + ...TestData.InstrumentCorrect, + name: "ESS instrument one", +}; + +const InstrumentCorrect2 = { + ...TestData.InstrumentCorrect, + name: "ESS instrument two", +}; + +const InstrumentCorrect3 = { + ...TestData.InstrumentCorrect, + name: "Another instrument at ESS, number three", +}; + +const InstrumentCorrect4 = { + ...TestData.InstrumentCorrect, + name: "Yet another instrument at ESS, number four", +}; + +describe("InstrumentFilter: Test retrieving instruments using filtering capabilities", () => { + beforeEach((done) => { + utils.getToken( + appUrl, + { + username: "ingestor", + password: "aman", + }, + (tokenVal) => { + accessTokenIngestor = tokenVal; + utils.getToken( + appUrl, + { + username: "user1", + password: "a609316768619f154ef58db4d847b75e", + }, + (tokenVal) => { + accessTokenUser1 = tokenVal; + utils.getToken( + appUrl, + { + username: "user2", + password: "f522d1d715970073a6413474ca0e0f63", + }, + (tokenVal) => { + accessTokenUser2 = tokenVal; + utils.getToken( + appUrl, + { + username: "user3", + password: "70dc489e8ee823ae815e18d664424df2", + }, + (tokenVal) => { + accessTokenUser3 = tokenVal; + utils.getToken( + appUrl, + { + username: "archiveManager", + password: "aman", + }, + (tokenVal) => { + accessTokenArchiveManager = tokenVal; + done(); + }, + ); + }, + ); + }, + ); + }, + ); + }, + ); + }); + + afterEach((done) => { + sandbox.restore(); + done(); + }); + + it("adds instrument 1", async () => { + return request(appUrl) + .post("/api/v3/Instruments") + .send(InstrumentCorrect1) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .expect(201) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("name").and.equal(InstrumentCorrect1.name); + instrumentPid1 = res.body["pid"]; + encodedInstrumentPid1 = encodeURIComponent(instrumentPid1); + }); + }); + + it("adds instrument 2", async () => { + return request(appUrl) + .post("/api/v3/Instruments") + .send(InstrumentCorrect2) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .expect(201) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("name").and.equal(InstrumentCorrect2.name); + instrumentPid2 = res.body["pid"]; + encodedInstrumentPid2 = encodeURIComponent(instrumentPid2); + }); + }); + + it("adds instrument 3", async () => { + return request(appUrl) + .post("/api/v3/Instruments") + .send(InstrumentCorrect3) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .expect(201) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("name").and.equal(InstrumentCorrect3.name); + instrumentPid3 = res.body["pid"]; + encodedInstrumentPid3 = encodeURIComponent(instrumentPid3); + }); + }); + + it("adds instrument 4", async () => { + return request(appUrl) + .post("/api/v3/Instruments") + .send(InstrumentCorrect4) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .expect(201) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("name").and.equal(InstrumentCorrect4.name); + instrumentPid4 = res.body["pid"]; + encodedInstrumentPid4 = encodeURIComponent(instrumentPid4); + }); + }); + + it("retrieve single instrument by its name", async () => { + const query = { where: { name: InstrumentCorrect1.name } }; + return request(appUrl) + .get("/api/v3/Instruments") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(1); + res.body[0]["pid"].should.be.equal(instrumentPid1); + }); + }); + + it("retrieve instruments with \"ESS instrument\" in name using loopback style \"like\" operator", async () => { + const query = { where: { name: { like: "ESS instrument" }}}; + return request(appUrl) + .get("/api/v3/Instruments") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(2); + }); + }); + + // it("count how many instruments with \"ESS instrument\" in name using loopback style \"like\" operator", async () => { + // const query = { where: { name: { like: "ESS instrument" }}}; + // return request(appUrl) + // .get("/api/v3/Instruments/count") + // .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + // .query("filter=" + encodeURIComponent(JSON.stringify(query))) + // .set("Accept", "application/json") + // .expect("Content-Type", /json/) + // .then((res) => { + // res.body["count"].should.be.equal(2); + // }); + // }); + + it("retrieve one instrument with \"ESS instrument\" in name using loopback style \"like\" operator", async () => { + const query = { where: { name: { like: "ESS instrument" }}}; + return request(appUrl) + .get("/api/v3/Instruments/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.oneOf([instrumentPid1, instrumentPid2]); + }); + }); + + it("retrieve instruments with \"ESS instrument\" in instrument name using mongo regex operator", async () => { + const query = { where: { name: { "$regex": "ESS instrument" }}}; + return request(appUrl) + .get("/api/v3/instruments") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(2); + }); + }); + + // it("count how many instruments with \"ESS instrument\" in instrument name using mongo regex operator", async () => { + // const query = { where: { name: { "$regex": "ESS instrument" }}}; + // return request(appUrl) + // .get("/api/v3/instruments/count") + // .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + // .query("filter=" + encodeURIComponent(JSON.stringify(query))) + // .set("Accept", "application/json") + // .expect("Content-Type", /json/) + // .then((res) => { + // res.body["count"].should.be.equal(3); + // }); + // }); + + it("retrieve one instruments with \"ESS instrument\" in instrument name using mongo regex operator", async () => { + const query = { where: { name: { "$regex": "ESS instrument" }}}; + return request(appUrl) + .get("/api/v3/instruments/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.oneOf([instrumentPid1, instrumentPid2]); + }); + }); + + + it("retrieve instruments with \"Another instrument\" in instrument name using loopback style \"like\" operator", async () => { + const query = { where: { name: { like: "Another instrument" }}}; + return request(appUrl) + .get("/api/v3/instruments") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(1); + res.body[0]["pid"].should.be.equal(instrumentPid3); + }); + }); + + it("retrieve one instrument with \"Another instrument\" in instrument name using loopback style \"like\" operator", async () => { + const query = { where: { name: { like: "Another instrument" }}}; + return request(appUrl) + .get("/api/v3/instruments/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.equal(instrumentPid3); + }); + }); + + // it("count how many instruments with \"Another instrument\" in instrument name using loopback style \"like\" operator", async () => { + // const query = { where: { name: { like: "Another instrument" }}}; + // return request(appUrl) + // .get("/api/v3/instruments/count") + // .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + // .query("filter=" + encodeURIComponent(JSON.stringify(query))) + // .set("Accept", "application/json") + // .expect("Content-Type", /json/) + // .then((res) => { + // res.body["count"].should.be.equal(1); + // }); + // }); + + it("retrieve instruments with \"Another instrument\" in instrument name using mongo \"regex\" operator", async () => { + const query = { where: { name: { "$regex": "Another instrument" }}}; + return request(appUrl) + .get("/api/v3/instruments") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(1); + res.body[0]["pid"].should.be.equal(instrumentPid3); + }); + }); + + it("retrieve one instrument with \"Another instrument\" in instrument name using mongo \"regex\" operator", async () => { + const query = { where: { name: { "$regex": "Another instrument" }}}; + return request(appUrl) + .get("/api/v3/instruments/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.equal(instrumentPid3); + }); + }); + + // it("count how many instruments with \"Another instrument\" in instrument name using mongo \"regex\" operator", async () => { + // const query = { where: { name: { "$regex": "Another instrument" }}}; + // return request(appUrl) + // .get("/api/v3/instruments/count") + // .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + // .query("filter=" + encodeURIComponent(JSON.stringify(query))) + // .set("Accept", "application/json") + // .expect("Content-Type", /json/) + // .then((res) => { + // res.body["count"].should.be.equal(1); + // }); + // }); + + it("retrieve instruments with \"another\" and \"instrument\" in name using \"regex\" operator", async () => { + const query = { where: { name: { "$regex": "[Aa]nother instrument" }}}; + return request(appUrl) + .get("/api/v3/instruments") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(2); + res.body[0]["pid"].should.be.oneOf([instrumentPid3, instrumentPid4]); + res.body[1]["pid"].should.be.oneOf([instrumentPid3, instrumentPid4]); + }); + }); + + it("retrieve one instrument with \"another\" and \"instrument\" in description using \"regex\" operator", async () => { + const query = { where: { name: { "$regex": "[Aa]nother instrument" }}}; + return request(appUrl) + .get("/api/v3/instruments/findOne") + .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .expect("Content-Type", /json/) + .then((res) => { + res.body["pid"].should.be.oneOf([instrumentPid3, instrumentPid4]); + }); + }); + + // it("count how many instruments with \"another\" and \"instrument\" in description using \"regex\" operator", async () => { + // const query = { where: { name: { "$regex": "[Aa]nother] instrument" }}}; + // return request(appUrl) + // .get("/api/v3/instruments/count") + // .set({ Authorization: `Bearer ${accessTokenIngestor}` }) + // .query("filter=" + encodeURIComponent(JSON.stringify(query))) + // .set("Accept", "application/json") + // .expect("Content-Type", /json/) + // .then((res) => { + // res.body["count"].should.be.equal(2); + // }); + // }); + + it("should delete instrument 1", async () => { + return request(appUrl) + .delete("/api/v3/instruments/" + instrumentPid1) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) + .expect(200) + .expect("Content-Type", /json/); + }); + + it("should delete instrument 2", async () => { + return request(appUrl) + .delete("/api/v3/instruments/" + instrumentPid2) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) + .expect(200) + .expect("Content-Type", /json/); + }); + + it("should delete instrument 3", async () => { + return request(appUrl) + .delete("/api/v3/instruments/" + instrumentPid3) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) + .expect(200) + .expect("Content-Type", /json/); + }); + + it("should delete instrument 4", async () => { + return request(appUrl) + .delete("/api/v3/instruments/" + instrumentPid4) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) + .expect(200) + .expect("Content-Type", /json/); + }); + +}); diff --git a/test/TestData.js b/test/TestData.js index e211c10be..b2e8a5cce 100644 --- a/test/TestData.js +++ b/test/TestData.js @@ -157,7 +157,7 @@ const TestData = { type: "raw", keywords: ["sls", "protein"], }, - + RawCorrectRandom: { principalInvestigator: faker.internet.email(), endTime: faker.date.past().toISOString(), @@ -681,6 +681,15 @@ const TestData = { pidArray: [], status: "pending_registration", }, + + InstrumentCorrect: { + name: "ESS1", + customMetadata: { + institute: "An immaginary intitution", + department: "An immaginary department", + } + }, + }; module.exports = { TestData };