[search] Unblock live test CI and add initial test (#8365)
* Add integration test tasks to eslint plugin * Fix GeographyPoint serialization * Add test and get it working inside node Since SearchServiceClient doesn't work in the browser, will have to investigate a way to run SearchIndexClient tests there.
This commit is contained in:
Родитель
619cf8c971
Коммит
abd85ef55d
|
@ -44,6 +44,9 @@
|
|||
"lint": "eslint src tests --ext .ts",
|
||||
"pack": "npm pack 2>&1",
|
||||
"prebuild": "npm run clean",
|
||||
"integration-test:browser": "echo skipped",
|
||||
"integration-test:node": "echo skipped",
|
||||
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
|
||||
"unit-test:node": "mocha --require source-map-support/register --timeout 10000 --full-trace --recursive dist/tests",
|
||||
"unit-test:browser": "echo skipped",
|
||||
"unit-test": "unit-test:node && unit-test:browser",
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"include": [
|
||||
"dist-esm/src/**/*.js"
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.d.ts",
|
||||
"dist-esm/src/generated/*"
|
||||
],
|
||||
"exclude-after-remap": false,
|
||||
"sourceMap": true,
|
||||
"produce-source-map": true,
|
||||
"instrument": true,
|
||||
"all": true
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
## 1.0.0-preview.3 (Unreleased)
|
||||
|
||||
- Fixed a bug where GeographyPoints were serialized incorrectly causing latitude and longitude to be flipped.
|
||||
|
||||
## 1.0.0-preview.2 (2020-04-06)
|
||||
|
||||
|
|
|
@ -92,6 +92,8 @@ const serviceClient = new SearchServiceClient("<endpoint>", new AzureKeyCredenti
|
|||
|
||||
`SearchServiceClient` provides methods for configuring and customizing an Azure Cognitive Search instance. The client currently has support for creating and managing search indexes and will later expand to support creating and managing other service entities such as indexers, synonym maps, cognitive skillsets, and data sources.
|
||||
|
||||
**Note**: This client cannot function in the browser because the APIs it calls do not have support for Cross-Origin Resource Sharing (CORS).
|
||||
|
||||
### Documents
|
||||
|
||||
An item stored inside a search index. The shape of this document is described in the index using `Field`s. Each Field has a name, a datatype, and additional metadata such as if it is searchable or filterable.
|
||||
|
@ -530,6 +532,7 @@ main();
|
|||
```
|
||||
|
||||
#### Get a list of existing indexers in the service
|
||||
|
||||
```js
|
||||
const { SearchServiceClient, AzureKeyCredential } = require("@azure/search-documents");
|
||||
|
||||
|
@ -538,7 +541,7 @@ const client = new SearchServiceClient("<endpoint>", new AzureKeyCredential("<ap
|
|||
async function main() {
|
||||
let listOfIndexers = await client.listIndexers();
|
||||
|
||||
for(let indexer of listOfIndexers) {
|
||||
for (let indexer of listOfIndexers) {
|
||||
console.log(`Name: ${indexer.name}`);
|
||||
console.log(`Datasource Name: ${indexer.dataSourceName}`);
|
||||
console.log(`Skillset Name: ${indexer.skillsetName}`);
|
||||
|
@ -550,6 +553,7 @@ main();
|
|||
```
|
||||
|
||||
#### Get a list of existing datasources in the service
|
||||
|
||||
```js
|
||||
const { SearchServiceClient, AzureKeyCredential } = require("@azure/search-documents");
|
||||
|
||||
|
@ -557,13 +561,13 @@ const client = new SearchServiceClient("<endpoint>", new AzureKeyCredential("<ap
|
|||
|
||||
async function main() {
|
||||
const listOfDataSources = await client.listDataSources();
|
||||
for(const dataSource of listOfDataSources) {
|
||||
for (const dataSource of listOfDataSources) {
|
||||
console.log(`Name: ${dataSource.name}`);
|
||||
console.log(`Description: ${dataSource.description}`);
|
||||
console.log(`DataSourceType: ${dataSource.type}`);
|
||||
console.log(`Credentials`);
|
||||
console.log(`\tConnectionString: ${dataSource.credentials.connectionString}`);
|
||||
console.log(`Container`)
|
||||
console.log(`Container`);
|
||||
console.log(`\tName: ${dataSource.container.name}`);
|
||||
console.log(`\tQuery: ${dataSource.container.query}`);
|
||||
console.log(`DataChangeDetectionPolicy: ${dataSource.dataChangeDetectionPolicy}`);
|
||||
|
@ -766,6 +770,7 @@ main();
|
|||
```
|
||||
|
||||
#### Create an Indexer
|
||||
|
||||
```js
|
||||
const { SearchServiceClient, AzureKeyCredential } = require("@azure/search-documents");
|
||||
|
||||
|
@ -773,18 +778,20 @@ const client = new SearchServiceClient("<endpoint>", new AzureKeyCredential("<ap
|
|||
|
||||
async function main() {
|
||||
const indexer = await client.createIndexer({
|
||||
name: 'my-azure-indexer-1',
|
||||
name: "my-azure-indexer-1",
|
||||
description: "My Azure Indexer 1",
|
||||
dataSourceName: "testblobstoragesjama",
|
||||
dataSourceName: "testblobstoragesjama",
|
||||
targetIndexName: "azureblob-index-2",
|
||||
isDisabled: false,
|
||||
fieldMappings: [{
|
||||
sourceFieldName: "metadata_storage_path",
|
||||
targetFieldName: "metadata_storage_path",
|
||||
mappingFunction: {
|
||||
name: "base64Encode"
|
||||
fieldMappings: [
|
||||
{
|
||||
sourceFieldName: "metadata_storage_path",
|
||||
targetFieldName: "metadata_storage_path",
|
||||
mappingFunction: {
|
||||
name: "base64Encode"
|
||||
}
|
||||
}
|
||||
}]
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -809,6 +816,7 @@ main();
|
|||
```
|
||||
|
||||
#### Create a DataSource
|
||||
|
||||
```js
|
||||
const { SearchServiceClient, AzureKeyCredential } = require("@azure/search-documents");
|
||||
|
||||
|
@ -818,22 +826,24 @@ const client = new SearchServiceClient("<endpoint>", new AzureKeyCredential("<ap
|
|||
// Ref: https://github.com/Azure-Samples/azure-search-java-samples/blob/master/search-java-indexer-demo/src/main/resources/com/microsoft/azure/search/samples/app/config.properties
|
||||
async function main() {
|
||||
const dataSource = await client.createDataSource({
|
||||
name: 'my-data-source-2',
|
||||
description: 'My Data Source 1',
|
||||
type: 'cosmosdb',
|
||||
name: "my-data-source-2",
|
||||
description: "My Data Source 1",
|
||||
type: "cosmosdb",
|
||||
container: {
|
||||
name: 'my-container-1'
|
||||
},
|
||||
credentials: {
|
||||
connectionString: 'AccountEndpoint=https://hotels-docbb.documents.azure.com:443/;AccountKey=4UPsNZyFAjgZ1tzHPGZaxS09XcwLrIawbXBWk6IixcxJoSePTcjBn0mi53XiKWu8MaUgowUhIovOv7kjksqAug==;Database=SampleData'
|
||||
name: "my-container-1"
|
||||
},
|
||||
})
|
||||
credentials: {
|
||||
connectionString:
|
||||
"AccountEndpoint=https://hotels-docbb.documents.azure.com:443/;AccountKey=4UPsNZyFAjgZ1tzHPGZaxS09XcwLrIawbXBWk6IixcxJoSePTcjBn0mi53XiKWu8MaUgowUhIovOv7kjksqAug==;Database=SampleData"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
#### Retrieve an existing indexer and modify a field in it
|
||||
|
||||
```js
|
||||
const { SearchServiceClient, AzureKeyCredential } = require("@azure/search-documents");
|
||||
|
||||
|
@ -843,35 +853,34 @@ async function main() {
|
|||
const indexer = await client.getIndexer("my-azure-indexer-1");
|
||||
indexer.isDisabled = true;
|
||||
indexer = await client.createOrUpdateIndexer(indexer);
|
||||
|
||||
|
||||
console.log(`Name: ${indexer.name}`);
|
||||
console.log(`Description: ${indexer.description}`);
|
||||
console.log(`Datasource Name: ${indexer.dataSourceName}`);
|
||||
console.log(`Target Index Name: ${indexer.targetIndexName}`);
|
||||
console.log(`IsDisabled: ${indexer.isDisabled}`);
|
||||
console.log(`Field Mappings`);
|
||||
for(let fieldMapping of indexer.fieldMappings) {
|
||||
for (let fieldMapping of indexer.fieldMappings) {
|
||||
console.log(`\tSource Field Name: ${fieldMapping.sourceFieldName}`);
|
||||
console.log(`\tTarget Field Name: ${fieldMapping.targetFieldName}`);
|
||||
console.log(`\tMapping Function Name: ${fieldMapping.mappingFunction.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
#### Retrieve an existing datasource and modify a field in it
|
||||
|
||||
```js
|
||||
const { SearchServiceClient, AzureKeyCredential } = require("@azure/search-documents");
|
||||
|
||||
const client = new SearchServiceClient("<endpoint>", new AzureKeyCredential("<apiKey>"));
|
||||
|
||||
async function main() {
|
||||
let dataSource = await client.getDataSource('my-data-source-2');
|
||||
let dataSource = await client.getDataSource("my-data-source-2");
|
||||
console.log(`Container Name: ${dataSource.container.name}`);
|
||||
dataSource.container.name = 'my-container-2';
|
||||
dataSource.container.name = "my-container-2";
|
||||
dataSource = await client.createOrUpdateDataSource(dataSource);
|
||||
console.log(`Container Name: ${dataSource.container.name}`);
|
||||
}
|
||||
|
@ -880,18 +889,19 @@ main();
|
|||
```
|
||||
|
||||
#### Get the status of an indexer
|
||||
|
||||
```js
|
||||
const { SearchServiceClient, AzureKeyCredential } = require("@azure/search-documents");
|
||||
|
||||
const client = new SearchServiceClient("<endpoint>", new AzureKeyCredential("<apiKey>"));
|
||||
|
||||
async function main() {
|
||||
const indexerStatus = await client.getIndexerStatus('my-azure-indexer-1');
|
||||
const indexerStatus = await client.getIndexerStatus("my-azure-indexer-1");
|
||||
console.log(`Name: ${indexerStatus.name}`);
|
||||
console.log(`OData Context: ${indexerStatus["@odata.context"]}`);
|
||||
console.log(`Status: ${indexerStatus.status}`);
|
||||
console.log(`Execution History`);
|
||||
for(let execution of indexerStatus.executionHistory) {
|
||||
for (let execution of indexerStatus.executionHistory) {
|
||||
console.log(`\tStatus: ${execution.status}`);
|
||||
console.log(`\tFinal Tracking State: ${execution.finalTrackingState}`);
|
||||
console.log(`\tInitial Tracking State: ${execution.initialTrackingState}`);
|
||||
|
@ -902,13 +912,14 @@ main();
|
|||
```
|
||||
|
||||
#### Get the service statistics
|
||||
|
||||
```js
|
||||
const { SearchServiceClient, AzureKeyCredential } = require("@azure/search-documents");
|
||||
|
||||
const client = new SearchServiceClient("<endpoint>", new AzureKeyCredential("<apiKey>"));
|
||||
|
||||
async function main() {
|
||||
const {counters, limits} = await client.getServiceStatistics();
|
||||
const { counters, limits } = await client.getServiceStatistics();
|
||||
console.log(`Counters`);
|
||||
console.log(`========`);
|
||||
console.log(`\tDocument Counter`);
|
||||
|
@ -937,8 +948,12 @@ async function main() {
|
|||
console.log(`======`);
|
||||
console.log(`\tMax Fields Per Index: ${limits.maxFieldsPerIndex}`);
|
||||
console.log(`\tMax Field Nesting Depth Per Index: ${limits.maxFieldNestingDepthPerIndex}`);
|
||||
console.log(`\tMax Complex Collection Fields Per Index: ${limits.maxComplexCollectionFieldsPerIndex}`);
|
||||
console.log(`\tMax Complex Objects In Collections Per Document: ${limits.maxComplexObjectsInCollectionsPerDocument}`);
|
||||
console.log(
|
||||
`\tMax Complex Collection Fields Per Index: ${limits.maxComplexCollectionFieldsPerIndex}`
|
||||
);
|
||||
console.log(
|
||||
`\tMax Complex Objects In Collections Per Document: ${limits.maxComplexObjectsInCollectionsPerDocument}`
|
||||
);
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
// https://github.com/karma-runner/karma-chrome-launcher
|
||||
process.env.CHROME_BIN = require("puppeteer").executablePath();
|
||||
|
||||
require("dotenv").config();
|
||||
const {
|
||||
jsonRecordingFilterFunction,
|
||||
isPlaybackMode,
|
||||
isSoftRecordMode,
|
||||
isRecordMode
|
||||
} = require("@azure/test-utils-recorder");
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
|
@ -20,16 +26,15 @@ module.exports = function(config) {
|
|||
"karma-env-preprocessor",
|
||||
"karma-coverage",
|
||||
"karma-remap-istanbul",
|
||||
"karma-junit-reporter"
|
||||
"karma-junit-reporter",
|
||||
"karma-json-to-file-reporter",
|
||||
"karma-json-preprocessor"
|
||||
],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
// Uncomment the cdn link below for the polyfill service to support IE11 missing features
|
||||
// Promise,String.prototype.startsWith,String.prototype.endsWith,String.prototype.repeat,String.prototype.includes,Array.prototype.includes,Object.keys
|
||||
// "https://cdn.polyfill.io/v2/polyfill.js?features=Symbol,Promise,String.prototype.startsWith,String.prototype.endsWith,String.prototype.repeat,String.prototype.includes,Array.prototype.includes,Object.keys|always",
|
||||
"dist-test/index.browser.js"
|
||||
],
|
||||
files: ["dist-test/index.browser.js"].concat(
|
||||
isPlaybackMode() || isSoftRecordMode() ? ["recordings/browsers/**/*.json"] : []
|
||||
),
|
||||
|
||||
// list of files / patterns to exclude
|
||||
exclude: [],
|
||||
|
@ -38,6 +43,7 @@ module.exports = function(config) {
|
|||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
"**/*.js": ["env"],
|
||||
"recordings/browsers/**/*.json": ["json"],
|
||||
// IMPORTANT: COMMENT following line if you want to debug in your browsers!!
|
||||
// Preprocess source file to calculate code coverage, however this will make source file unreadable
|
||||
"test-browser/index.js": ["coverage"]
|
||||
|
@ -46,12 +52,12 @@ module.exports = function(config) {
|
|||
// inject following environment values into browser testing with window.__env__
|
||||
// environment values MUST be exported or set with same console running "karma start"
|
||||
// https://www.npmjs.com/package/karma-env-preprocessor
|
||||
envPreprocessor: ["ACCOUNT_NAME", "ACCOUNT_SAS"],
|
||||
envPreprocessor: ["TEST_MODE", "ENDPOINT", "SEARCH_API_ADMIN_KEY", "SEARCH_API_ADMIN_KEY_ALT"],
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ["mocha", "coverage", "karma-remap-istanbul", "junit"],
|
||||
reporters: ["mocha", "coverage", "karma-remap-istanbul", "junit", "json-to-file"],
|
||||
|
||||
coverageReporter: {
|
||||
dir: "coverage-browser/",
|
||||
|
@ -78,6 +84,11 @@ module.exports = function(config) {
|
|||
properties: {} // key value pair of properties to add to the <properties> section of the report
|
||||
},
|
||||
|
||||
jsonToFileReporter: {
|
||||
filter: jsonRecordingFilterFunction,
|
||||
outputPath: "."
|
||||
},
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
|
@ -108,6 +119,10 @@ module.exports = function(config) {
|
|||
browserDisconnectTimeout: 10000,
|
||||
browserDisconnectTolerance: 3,
|
||||
|
||||
browserConsoleLogOptions: {
|
||||
terminal: !isRecordMode()
|
||||
},
|
||||
|
||||
client: {
|
||||
mocha: {
|
||||
// change Karma's debug.html to the mocha web reporter
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
"execute:samples": "npm run build:samples && npm run execute:js-samples && npm run execute:ts-samples",
|
||||
"extract-api": "tsc -p . && api-extractor run --local",
|
||||
"format": "prettier --write --config ../../.prettierrc.json \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
|
||||
"integration-test:browser": "echo skipped",
|
||||
"integration-test:node": "echo skipped",
|
||||
"integration-test:browser": "karma start --single-run",
|
||||
"integration-test:node": "nyc mocha -r esm --require source-map-support/register --reporter ../../../common/tools/mocha-multi-reporter.js --timeout 5000000 --full-trace dist-esm/test/**/*.spec.js",
|
||||
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
|
||||
"lint:fix": "eslint package.json api-extractor.json src test --ext .ts --fix --fix-type [problem,suggestion]",
|
||||
"lint": "eslint package.json api-extractor.json src test --ext .ts -f html -o search-lintReport.html || exit 0",
|
||||
|
@ -29,7 +29,7 @@
|
|||
"prebuild": "npm run clean",
|
||||
"test:browser": "npm run build:test && npm run unit-test:browser && npm run integration-test:browser",
|
||||
"test:node": "npm run build:test && npm run unit-test:node && npm run integration-test:node",
|
||||
"test": "npm run build:test && npm run unit-test && npm run integration-test",
|
||||
"test": "npm run build:test && npm run unit-test",
|
||||
"unit-test:browser": "karma start --single-run",
|
||||
"unit-test:node": "mocha --reporter ../../../common/tools/mocha-multi-reporter.js dist-test/index.node.js",
|
||||
"unit-test": "npm run unit-test:node && npm run unit-test:browser"
|
||||
|
@ -86,6 +86,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
|
||||
"@azure/test-utils-recorder": "^1.0.0",
|
||||
"@microsoft/api-extractor": "^7.5.4",
|
||||
"@rollup/plugin-json": "^4.0.0",
|
||||
"@rollup/plugin-multi-entry": "^3.0.0",
|
||||
|
@ -112,17 +113,21 @@
|
|||
"karma-env-preprocessor": "^0.1.1",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-ie-launcher": "^1.0.0",
|
||||
"karma-json-preprocessor": "^0.3.3",
|
||||
"karma-json-to-file-reporter": "^1.0.1",
|
||||
"karma-junit-reporter": "^2.0.1",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-remap-istanbul": "^0.6.0",
|
||||
"mocha": "^7.1.1",
|
||||
"mocha-junit-reporter": "^1.18.0",
|
||||
"nyc": "^14.0.0",
|
||||
"prettier": "^1.16.4",
|
||||
"rimraf": "^3.0.0",
|
||||
"rollup": "^1.16.3",
|
||||
"@rollup/plugin-commonjs": "^11.0.1",
|
||||
"@rollup/plugin-node-resolve": "^7.0.0",
|
||||
"rollup-plugin-shim": "^1.0.0",
|
||||
"rollup-plugin-sourcemaps": "^0.4.2",
|
||||
"rollup-plugin-terser": "^5.1.1",
|
||||
"rollup-plugin-visualizer": "^3.1.1",
|
||||
|
|
37
sdk/search/search-documents/recordings/node/searchindexclient_count/recording_returns_the_correct_document_count.js
сгенерированный
Normal file
37
sdk/search/search-documents/recordings/node/searchindexclient_count/recording_returns_the_correct_document_count.js
сгенерированный
Normal file
|
@ -0,0 +1,37 @@
|
|||
let nock = require('nock');
|
||||
|
||||
module.exports.hash = "427bbfd10e4ff3fd2e4b5b0e06c3d419";
|
||||
|
||||
module.exports.testInfo = {"uniqueName":{},"newDate":{}}
|
||||
|
||||
nock('https://endpoint:443', {"encodedQueryParams":true})
|
||||
.get('/indexes(%27hotel-live-test%27)/docs/$count')
|
||||
.query(true)
|
||||
.reply(200, ["1f8b0800000000000400edbd07601c499625262f6dca7b7f4af54ad7e074a10880601324d8904010ecc188cde692ec1d69472329ab2a81ca6556655d661640cced9dbcf7de7befbdf7de7befbdf7ba3b9d4e27f7dfff3f5c6664016cf6ce4adac99e2180aac81f3f7e7c1f3f22fec7bff71fdcddf97f00bbe0538805000000"], [
|
||||
'Cache-Control',
|
||||
'no-cache',
|
||||
'Pragma',
|
||||
'no-cache',
|
||||
'Content-Type',
|
||||
'text/plain',
|
||||
'Content-Encoding',
|
||||
'gzip',
|
||||
'Expires',
|
||||
'-1',
|
||||
'Vary',
|
||||
'Accept-Encoding',
|
||||
'request-id',
|
||||
'c40c4c53-eec8-458c-9d3c-dc8d4b1dc41c',
|
||||
'elapsed-time',
|
||||
'3',
|
||||
'OData-Version',
|
||||
'4.0',
|
||||
'Preference-Applied',
|
||||
'odata.include-annotations="*"',
|
||||
'Strict-Transport-Security',
|
||||
'max-age=15724800; includeSubDomains',
|
||||
'Date',
|
||||
'Thu, 16 Apr 2020 00:06:03 GMT',
|
||||
'Content-Length',
|
||||
'127'
|
||||
]);
|
|
@ -3,6 +3,7 @@ import nodeResolve from "@rollup/plugin-node-resolve";
|
|||
import multiEntry from "@rollup/plugin-multi-entry";
|
||||
import cjs from "@rollup/plugin-commonjs";
|
||||
import replace from "@rollup/plugin-replace";
|
||||
import shim from "rollup-plugin-shim";
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
import sourcemaps from "rollup-plugin-sourcemaps";
|
||||
import viz from "rollup-plugin-visualizer";
|
||||
|
@ -14,7 +15,7 @@ const input = "dist-esm/src/index.js";
|
|||
const production = process.env.NODE_ENV === "production";
|
||||
|
||||
export function nodeConfig(test = false) {
|
||||
const externalNodeBuiltins = ["events"];
|
||||
const externalNodeBuiltins = ["events", "path"];
|
||||
const baseConfig = {
|
||||
input: input,
|
||||
external: depNames.concat(externalNodeBuiltins),
|
||||
|
@ -68,6 +69,7 @@ export function browserConfig(test = false) {
|
|||
globals: { "@azure/core-http": "Azure.Core.HTTP" }
|
||||
},
|
||||
preserveSymlinks: false,
|
||||
external: ["fs-extra"],
|
||||
plugins: [
|
||||
sourcemaps(),
|
||||
replace({
|
||||
|
@ -79,6 +81,13 @@ export function browserConfig(test = false) {
|
|||
"if (isNode)": "if (false)"
|
||||
}
|
||||
}),
|
||||
shim({
|
||||
constants: `export default {}`,
|
||||
fs: `export default {}`,
|
||||
os: `export default {}`,
|
||||
dotenv: `export function config() { }`,
|
||||
path: `export default {}`
|
||||
}),
|
||||
nodeResolve({
|
||||
mainFields: ["module", "browser"],
|
||||
preferBuiltins: false
|
||||
|
|
|
@ -33,7 +33,7 @@ export default class GeographyPoint {
|
|||
public toJSON(): object {
|
||||
return {
|
||||
type: "Point",
|
||||
coordinates: [this.latitude, this.longitude],
|
||||
coordinates: [this.longitude, this.latitude],
|
||||
crs: { type: "name", properties: { name: WorldGeodeticSystem1984 } }
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ describe("geographyPoint", () => {
|
|||
const result = JSON.parse(JSON.stringify(geoPoint));
|
||||
assert.deepEqual(result, {
|
||||
type: "Point",
|
||||
coordinates: [47.669444, -122.123889],
|
||||
coordinates: [-122.123889, 47.669444],
|
||||
crs: { type: "name", properties: { name: "EPSG:4326" } }
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
/* eslint-disable no-invalid-this */
|
||||
|
||||
import { assert } from "chai";
|
||||
|
||||
import { Recorder, record, isPlaybackMode } from "@azure/test-utils-recorder";
|
||||
|
||||
import { createClients, environmentSetup } from "../utils/recordedClient";
|
||||
import { SearchIndexClient, SearchServiceClient } from "../../src/index";
|
||||
import { Hotel } from "../utils/interfaces";
|
||||
import { createIndex, populateIndex } from "../utils/setupIndex";
|
||||
|
||||
const TEST_INDEX_NAME = "hotel-live-test";
|
||||
|
||||
describe("SearchIndexClient", function() {
|
||||
let recorder: Recorder;
|
||||
let indexClient: SearchIndexClient<Hotel>;
|
||||
let serviceClient: SearchServiceClient;
|
||||
|
||||
this.timeout(30000);
|
||||
|
||||
beforeEach(async function() {
|
||||
({ indexClient, serviceClient } = createClients<Hotel>(TEST_INDEX_NAME));
|
||||
if (!isPlaybackMode()) {
|
||||
await createIndex(serviceClient, TEST_INDEX_NAME);
|
||||
await populateIndex(indexClient);
|
||||
}
|
||||
recorder = record(this, environmentSetup);
|
||||
// create the clients again, but hooked up to the recorder
|
||||
({ indexClient, serviceClient } = createClients<Hotel>(TEST_INDEX_NAME));
|
||||
});
|
||||
|
||||
afterEach(async function() {
|
||||
if (recorder) {
|
||||
recorder.stop();
|
||||
}
|
||||
if (!isPlaybackMode()) {
|
||||
await serviceClient.deleteIndex(TEST_INDEX_NAME);
|
||||
}
|
||||
});
|
||||
|
||||
describe("#count", function() {
|
||||
it("returns the correct document count", async function() {
|
||||
const documentCount = await indexClient.countDocuments();
|
||||
assert.equal(documentCount, 10);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { GeographyPoint } from "../../src/index";
|
||||
|
||||
export interface Hotel {
|
||||
hotelId: string;
|
||||
hotelName?: string | null;
|
||||
description?: string | null;
|
||||
descriptionFr?: string | null;
|
||||
category?: string | null;
|
||||
tags?: string[] | null;
|
||||
parkingIncluded?: boolean | null;
|
||||
smokingAllowed?: boolean | null;
|
||||
lastRenovationDate?: Date | null;
|
||||
rating?: number | null;
|
||||
location?: GeographyPoint | null;
|
||||
address?: {
|
||||
streetAddress?: string | null;
|
||||
city?: string | null;
|
||||
stateProvince?: string | null;
|
||||
postalCode?: string | null;
|
||||
country?: string | null;
|
||||
} | null;
|
||||
rooms?: Array<{
|
||||
description?: string | null;
|
||||
descriptionFr?: string | null;
|
||||
type?: string | null;
|
||||
baseRate?: number | null;
|
||||
bedOptions?: string | null;
|
||||
sleepsCount?: number | null;
|
||||
smokingAllowed?: boolean | null;
|
||||
tags?: string[] | null;
|
||||
}> | null;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import * as path from "path";
|
||||
|
||||
import { env, RecorderEnvironmentSetup } from "@azure/test-utils-recorder";
|
||||
import { isNode } from "@azure/core-http";
|
||||
|
||||
import { AzureKeyCredential, SearchIndexClient, SearchServiceClient } from "../../src/index";
|
||||
|
||||
if (isNode) {
|
||||
dotenv.config({ path: path.join(__dirname, "..", ".env") });
|
||||
}
|
||||
|
||||
export interface Clients<IndexModel> {
|
||||
indexClient: SearchIndexClient<IndexModel>;
|
||||
serviceClient: SearchServiceClient;
|
||||
}
|
||||
|
||||
const replaceableVariables: { [k: string]: string } = {
|
||||
SEARCH_API_ADMIN_KEY: "admin_key",
|
||||
SEARCH_API_ADMIN_KEY_ALT: "admin_key_alt",
|
||||
ENDPOINT: "https://endpoint"
|
||||
};
|
||||
|
||||
export const testEnv = new Proxy(replaceableVariables, {
|
||||
get: (target, key: string) => {
|
||||
return env[key] || target[key];
|
||||
}
|
||||
});
|
||||
|
||||
export const environmentSetup: RecorderEnvironmentSetup = {
|
||||
replaceableVariables,
|
||||
customizationsOnRecordings: [
|
||||
(recording: string): string =>
|
||||
recording.replace(/"access_token"\s?:\s?"[^"]*"/g, `"access_token":"access_token"`),
|
||||
// If we put ENDPOINT in replaceableVariables above, it will not capture
|
||||
// the endpoint string used with nock, which will be expanded to
|
||||
// https://<endpoint>:443/ and therefore will not match, so we have to do
|
||||
// this instead.
|
||||
(recording: string): string => {
|
||||
const match = testEnv.ENDPOINT.replace(/^https:\/\//, "").replace(/\/$/, "");
|
||||
return recording.replace(match, "endpoint");
|
||||
}
|
||||
],
|
||||
queryParametersToSkip: []
|
||||
};
|
||||
|
||||
export function createClients<IndexModel>(indexName: string): Clients<IndexModel> {
|
||||
const credential = new AzureKeyCredential(testEnv.SEARCH_API_ADMIN_KEY);
|
||||
const indexClient = new SearchIndexClient<IndexModel>(testEnv.ENDPOINT, indexName, credential);
|
||||
const serviceClient = new SearchServiceClient(testEnv.ENDPOINT, credential);
|
||||
|
||||
return {
|
||||
indexClient,
|
||||
serviceClient
|
||||
};
|
||||
}
|
|
@ -0,0 +1,417 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
SearchIndexClient,
|
||||
SearchServiceClient,
|
||||
GeographyPoint,
|
||||
Index,
|
||||
KnownAnalyzerNames
|
||||
} from "../../src/index";
|
||||
import { Hotel } from "./interfaces";
|
||||
import { delay } from "@azure/core-http";
|
||||
|
||||
// eslint-disable-next-line @azure/azure-sdk/ts-use-interface-parameters
|
||||
export async function createIndex(client: SearchServiceClient, name: string): Promise<void> {
|
||||
const hotelIndex: Index = {
|
||||
name,
|
||||
fields: [
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "hotelId",
|
||||
key: true,
|
||||
filterable: true,
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "hotelName",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "description",
|
||||
searchable: true,
|
||||
analyzer: KnownAnalyzerNames.EnLucene
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "descriptionFr",
|
||||
searchable: true,
|
||||
analyzer: KnownAnalyzerNames.FrLucene
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "category",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Collection(Edm.String)",
|
||||
name: "tags",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.Boolean",
|
||||
name: "parkingIncluded",
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.Boolean",
|
||||
name: "smokingAllowed",
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.DateTimeOffset",
|
||||
name: "lastRenovationDate",
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.Int32",
|
||||
name: "rating",
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.GeographyPoint",
|
||||
name: "location",
|
||||
filterable: true,
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.ComplexType",
|
||||
name: "address",
|
||||
fields: [
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "streetAddress",
|
||||
searchable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "city",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "stateProvince",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "country",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "postalCode",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
facetable: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "Collection(Edm.ComplexType)",
|
||||
name: "rooms",
|
||||
fields: [
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "description",
|
||||
searchable: true,
|
||||
analyzer: KnownAnalyzerNames.EnLucene
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "descriptionFr",
|
||||
searchable: true,
|
||||
analyzer: KnownAnalyzerNames.FrLucene
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "type",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.Double",
|
||||
name: "baseRate",
|
||||
filterable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.String",
|
||||
name: "bedOptions",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.Int32",
|
||||
name: "sleepsCount",
|
||||
filterable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Edm.Boolean",
|
||||
name: "smokingAllowed",
|
||||
filterable: true,
|
||||
facetable: true
|
||||
},
|
||||
{
|
||||
type: "Collection(Edm.String)",
|
||||
name: "tags",
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
facetable: true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
suggesters: [
|
||||
{
|
||||
name: "sg",
|
||||
sourceFields: ["description", "hotelName"]
|
||||
}
|
||||
],
|
||||
scoringProfiles: [
|
||||
{
|
||||
name: "nearest",
|
||||
functionAggregation: "sum",
|
||||
functions: [
|
||||
{
|
||||
type: "distance",
|
||||
fieldName: "location",
|
||||
boost: 2,
|
||||
parameters: {
|
||||
referencePointParameter: "myloc",
|
||||
boostingDistance: 100
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
corsOptions: {
|
||||
// for browser tests
|
||||
allowedOrigins: ["*"]
|
||||
}
|
||||
};
|
||||
await client.createIndex(hotelIndex);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @azure/azure-sdk/ts-use-interface-parameters
|
||||
export async function populateIndex(client: SearchIndexClient<Hotel>): Promise<void> {
|
||||
// test data from https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/search/Azure.Search.Documents/tests/Utilities/SearchResources.Data.cs
|
||||
const testDocuments: Hotel[] = [
|
||||
{
|
||||
hotelId: "1",
|
||||
description:
|
||||
"Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa, " +
|
||||
"and a really helpful concierge. The location is perfect -- right downtown, close to all " +
|
||||
"the tourist attractions. We highly recommend this hotel.",
|
||||
descriptionFr:
|
||||
"Meilleur hôtel en ville si vous aimez les hôtels de luxe. Ils ont une magnifique piscine " +
|
||||
"à débordement, un spa et un concierge très utile. L'emplacement est parfait – en plein " +
|
||||
"centre, à proximité de toutes les attractions touristiques. Nous recommandons fortement " +
|
||||
"cet hôtel.",
|
||||
hotelName: "Fancy Stay",
|
||||
category: "Luxury",
|
||||
tags: ["pool", "view", "wifi", "concierge"],
|
||||
parkingIncluded: false,
|
||||
smokingAllowed: false,
|
||||
lastRenovationDate: new Date(2010, 5, 27),
|
||||
rating: 5,
|
||||
location: new GeographyPoint(47.678581, -122.131577)
|
||||
},
|
||||
{
|
||||
hotelId: "2",
|
||||
description: "Cheapest hotel in town. Infact, a motel.",
|
||||
descriptionFr: "Hôtel le moins cher en ville. Infact, un motel.",
|
||||
hotelName: "Roach Motel",
|
||||
category: "Budget",
|
||||
tags: ["motel", "budget"],
|
||||
parkingIncluded: true,
|
||||
smokingAllowed: true,
|
||||
lastRenovationDate: new Date(1982, 3, 28),
|
||||
rating: 1,
|
||||
location: new GeographyPoint(49.678581, -122.131577)
|
||||
},
|
||||
{
|
||||
hotelId: "3",
|
||||
description: "Very popular hotel in town",
|
||||
descriptionFr: "Hôtel le plus populaire en ville",
|
||||
hotelName: "EconoStay",
|
||||
category: "Budget",
|
||||
tags: ["wifi", "budget"],
|
||||
parkingIncluded: true,
|
||||
smokingAllowed: false,
|
||||
lastRenovationDate: new Date(1995, 6, 1),
|
||||
rating: 4,
|
||||
location: new GeographyPoint(46.678581, -122.131577)
|
||||
},
|
||||
{
|
||||
hotelId: "4",
|
||||
description: "Pretty good hotel",
|
||||
descriptionFr: "Assez bon hôtel",
|
||||
hotelName: "Express Rooms",
|
||||
category: "Budget",
|
||||
tags: ["wifi", "budget"],
|
||||
parkingIncluded: true,
|
||||
smokingAllowed: false,
|
||||
lastRenovationDate: new Date(1995, 6, 1),
|
||||
rating: 4,
|
||||
location: new GeographyPoint(46.678581, -122.131577)
|
||||
},
|
||||
{
|
||||
hotelId: "5",
|
||||
description: "Another good hotel",
|
||||
descriptionFr: "Un autre bon hôtel",
|
||||
hotelName: "Comfy Place",
|
||||
category: "Budget",
|
||||
tags: ["wifi", "budget"],
|
||||
parkingIncluded: true,
|
||||
smokingAllowed: false,
|
||||
lastRenovationDate: new Date(2012, 7, 12),
|
||||
rating: 4,
|
||||
location: new GeographyPoint(48.678581, -122.131577)
|
||||
},
|
||||
{
|
||||
hotelId: "6",
|
||||
description: "Surprisingly expensive. Model suites have an ocean-view.",
|
||||
lastRenovationDate: null
|
||||
},
|
||||
{
|
||||
hotelId: "7",
|
||||
description: "Modern architecture, very polite staff and very clean. Also very affordable.",
|
||||
descriptionFr: "Architecture moderne, personnel poli et très propre. Aussi très abordable.",
|
||||
hotelName: "Modern Stay"
|
||||
},
|
||||
{
|
||||
hotelId: "8",
|
||||
description:
|
||||
"Has some road noise and is next to the very police station. Bathrooms had morel coverings.",
|
||||
descriptionFr:
|
||||
"Il y a du bruit de la route et se trouve à côté de la station de police. Les salles de bain avaient des revêtements de morilles."
|
||||
},
|
||||
{
|
||||
hotelId: "9",
|
||||
hotelName: "Secret Point Motel",
|
||||
description:
|
||||
"The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
|
||||
descriptionFr:
|
||||
"L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
|
||||
category: "Boutique",
|
||||
tags: ["pool", "air conditioning", "concierge"],
|
||||
parkingIncluded: false,
|
||||
smokingAllowed: true,
|
||||
lastRenovationDate: new Date(1970, 0, 18),
|
||||
rating: 4,
|
||||
location: new GeographyPoint(40.760586, -73.975403),
|
||||
address: {
|
||||
streetAddress: "677 5th Ave",
|
||||
city: "New York",
|
||||
stateProvince: "NY",
|
||||
country: "USA",
|
||||
postalCode: "10022"
|
||||
},
|
||||
rooms: [
|
||||
{
|
||||
description: "Budget Room, 1 Queen Bed (Cityside)",
|
||||
descriptionFr: "Chambre Économique, 1 grand lit (côté ville)",
|
||||
type: "Budget Room",
|
||||
baseRate: 9.69,
|
||||
bedOptions: "1 Queen Bed",
|
||||
sleepsCount: 2,
|
||||
smokingAllowed: true,
|
||||
tags: ["vcr/dvd"]
|
||||
},
|
||||
{
|
||||
description: "Budget Room, 1 King Bed (Mountain View)",
|
||||
descriptionFr: "Chambre Économique, 1 très grand lit (Mountain View)",
|
||||
type: "Budget Room",
|
||||
baseRate: 8.09,
|
||||
bedOptions: "1 King Bed",
|
||||
sleepsCount: 2,
|
||||
smokingAllowed: true,
|
||||
tags: ["vcr/dvd", "jacuzzi tub"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
hotelId: "10",
|
||||
hotelName: "Countryside Hotel",
|
||||
description:
|
||||
"Save up to 50% off traditional hotels. Free WiFi, great location near downtown, full kitchen, washer & dryer, 24/7 support, bowling alley, fitness center and more.",
|
||||
descriptionFr:
|
||||
"Économisez jusqu'à 50% sur les hôtels traditionnels. WiFi gratuit, très bien situé près du centre-ville, cuisine complète, laveuse & sécheuse, support 24/7, bowling, centre de fitness et plus encore.",
|
||||
category: "Budget",
|
||||
tags: ["24-hour front desk service", "coffee in lobby", "restaurant"],
|
||||
parkingIncluded: false,
|
||||
smokingAllowed: true,
|
||||
lastRenovationDate: new Date(1999, 8, 6),
|
||||
rating: 3,
|
||||
location: new GeographyPoint(35.90416, -78.940483),
|
||||
address: {
|
||||
streetAddress: "6910 Fayetteville Rd",
|
||||
city: "Durham",
|
||||
stateProvince: "NC",
|
||||
country: "USA",
|
||||
postalCode: "27713"
|
||||
},
|
||||
rooms: [
|
||||
{
|
||||
description: "Suite, 1 King Bed (Amenities)",
|
||||
descriptionFr: "Suite, 1 très grand lit (Services)",
|
||||
type: "Suite",
|
||||
baseRate: 2.44,
|
||||
bedOptions: "1 King Bed",
|
||||
sleepsCount: 2,
|
||||
smokingAllowed: true,
|
||||
tags: ["coffee maker"]
|
||||
},
|
||||
{
|
||||
description: "Budget Room, 1 Queen Bed (Amenities)",
|
||||
descriptionFr: "Chambre Économique, 1 grand lit (Services)",
|
||||
type: "Budget Room",
|
||||
baseRate: 7.69,
|
||||
bedOptions: "1 Queen Bed",
|
||||
sleepsCount: 2,
|
||||
smokingAllowed: false,
|
||||
tags: ["coffee maker"]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
await client.uploadDocuments(testDocuments);
|
||||
|
||||
let count = await client.countDocuments();
|
||||
while (count !== testDocuments.length) {
|
||||
await delay(2000);
|
||||
count = await client.countDocuments();
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче