diff --git a/.circleci/config.yml b/.circleci/config.yml index d8d281b1e28..4e31acfe35a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -263,7 +263,7 @@ jobs: name: Unit & Integration tests command: yarn run test:ci:v4 - store_test_results: - path: junit/jest/ + path: junit/vitest/ - run: name: Type Checking command: yarn run type-check:v4 @@ -282,9 +282,9 @@ jobs: yarn run prepare-vue3 - run: name: Vue Unit tests - command: yarn run jest packages/vue-instantsearch --ci --maxWorkers=4 + command: VUE_VERSION=3 yarn vitest run packages/vue-instantsearch --pool=threads --maxWorkers=4 - store_test_results: - path: junit/jest/ + path: junit/vitest/ - run: name: Vue 3 Test Exports command: yarn workspace vue-instantsearch run test:exports:vue3 @@ -302,7 +302,7 @@ jobs: name: Unit tests command: yarn run test:ci - store_test_results: - path: junit/jest/ + path: junit/vitest/ examples: <<: *defaults diff --git a/babel.config.js b/babel.config.js index 86790e55f63..32db89e1e54 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,13 +1,12 @@ /** - * Babel configuration for Jest tests only. - * Build transpilation is now handled by SWC via rollup-plugin-swc3. + * Babel configuration for Storybook only. + * Build transpilation is handled by SWC via rollup-plugin-swc3. + * Test transpilation is handled by Vite via Vitest. * * @param {Object} api - Babel config API. * @returns {Object} Babel config. */ module.exports = (api) => { - const isStorybook = api.env('storybook'); - api.cache(true); return { @@ -16,24 +15,16 @@ module.exports = (api) => { ['@babel/preset-react', { runtime: 'classic' }], [ '@babel/preset-env', - isStorybook - ? { - modules: false, - // Ensure optional chaining/nullish coalescing are transformed - targets: { - ie: 11, - }, - } - : { - modules: 'commonjs', - targets: { - node: true, - }, - }, + { + modules: false, + // Ensure optional chaining/nullish coalescing are transformed + targets: { + ie: 11, + }, + }, ], ], plugins: [ - // Class properties for test files '@babel/plugin-proposal-class-properties', ], }; diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 85bcdae6c9f..00000000000 --- a/jest.config.js +++ /dev/null @@ -1,87 +0,0 @@ -// @ts-check - -/** @type {any} */ -const packagejson = require('./package.json'); -/** @type {'3' | '4' | '5'} */ -const algoliaSearchMajor = - packagejson.devDependencies.algoliasearch.split('.')[0]; - -/** @type {import('@jest/types').Config.InitialOptions} */ -const config = { - rootDir: process.cwd(), - testRunner: 'jest-circus', - testEnvironment: '@instantsearch/testutils/jest-environment-node.ts', - setupFilesAfterEnv: ['./tests/utils/setupTests.ts'], - testPathIgnorePatterns: [ - '/node_modules/', - '/packages/*/node_modules/', - '/packages/*/dist*', - '/tests/e2e/*', - '/examples/', - '/packages/algoliasearch-helper', - '/packages/create-instantsearch-app', - '/packages/react-instantsearch-router-nextjs/__tests__', - '/packages/react-instantsearch-nextjs/__tests__', - '/__utils__/', - algoliaSearchMajor !== '5' && '/packages/algolia-experiences', - ].filter((x) => x !== false), - watchPathIgnorePatterns: [ - '/packages/*/cjs', - '/packages/*/dist', - '/packages/*/es', - '/packages/*/stories', - '/examples', - '/website', - ], - watchPlugins: [ - 'jest-watch-typeahead/filename', - 'jest-watch-typeahead/testname', - ], - transformIgnorePatterns: [ - 'node_modules/(?!(search-insights|algoliasearch|zod)/)', - ], - transform: { - '^.+\\.(j|t)sx?$': 'babel-jest', - '^.+\\.vue$': '@vue/vue2-jest', - }, - moduleFileExtensions: ['tsx', 'ts', 'js', 'vue'], - moduleNameMapper: { - '^react-instantsearch$': '/packages/react-instantsearch/src/', - '^react-instantsearch-core/dist/es(.*)$': - '/packages/react-instantsearch-core/src$1', - '^react-instantsearch-(.*[^v6])$': - '/packages/react-instantsearch-$1/src/', - '^instantsearch.js$': '/packages/instantsearch.js/src/', - '^instantsearch.js/es(.*)$': '/packages/instantsearch.js/src$1', - '^instantsearch.js/(.*)$': '/packages/instantsearch.js/$1', - '^instantsearch-ui-components$': - '/packages/instantsearch-ui-components/src/', - '^instantsearch-ui-components/(.*)$': - '/packages/instantsearch-ui-components/$1', - }, - modulePathIgnorePatterns: [ - '/packages/create-instantsearch-app/src/templates', - ], - globals: { - __DEV__: true, - 'ts-jest': {}, - }, - snapshotFormat: { - printBasicPrototype: false, - }, - // reporter for circleci - reporters: [ - 'default', - [ - 'jest-junit', - { - outputDirectory: 'junit/jest', - suiteNameTemplate: '{filepath}', - ancestorSeparator: ' › ', - addFileAttribute: 'true', - }, - ], - ], -}; - -module.exports = config; diff --git a/package.json b/package.json index 5edf92367cb..b62f4b0ba09 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,9 @@ "type-check": "tsc && lerna run type-check", "type-check:v3": "tsc --project tsconfig.v3.json", "type-check:v4": "tsc --project tsconfig.v4.json", - "test": "jest && lerna run test", - "test:ci": "./scripts/retry.sh 3 'jest --maxWorkers=4 --ci' && lerna run test --concurrency=1", - "test:ci:v4": "./scripts/retry.sh 3 'jest --maxWorkers=4 --ci' && lerna run test:v4 --concurrency=1", + "test": "vitest run && lerna run test", + "test:ci": "./scripts/retry.sh 3 'vitest run --pool=threads --maxWorkers=4' && lerna run test --concurrency=1", + "test:ci:v4": "./scripts/retry.sh 3 'vitest run --pool=threads --maxWorkers=4' && lerna run test:v4 --concurrency=1", "test:size": "bundlesize", "test:exports": "lerna run test:exports", "test:versions": "./tests/versions/index.js", @@ -66,14 +66,12 @@ "@swc/core": "1.15.11", "@swc/helpers": "0.5.18", "@testing-library/dom": "8.18.1", - "@testing-library/jest-dom": "5.16.5", + "@testing-library/jest-dom": "6", "@testing-library/preact": "3.2.2", "@testing-library/react": "16.1.0", "@testing-library/user-event": "13.5.0", "@types/enzyme": "^3.1.15", "@types/googlemaps": "^3.30.16", - "@types/jest": "^27.4.0", - "@types/jest-diff": "^24.3.0", "@types/jsdom": "16.2.13", "@types/prop-types": "^15.5.8", "@types/react": "19.0.3", @@ -81,8 +79,11 @@ "@types/react-test-renderer": "19.0.0", "@types/storybook__addon-actions": "3.4.2", "@types/storybook__addon-knobs": "^5.0.0", - "@vue/vue2-jest": "27", - "@vue/vue3-jest": "27", + "@typescript-eslint/eslint-plugin": "5.38.1", + "@typescript-eslint/parser": "4.31.2", + "@vitejs/plugin-vue": "6.0.5", + "@vitejs/plugin-vue2": "2.3.4", + "@vitest/coverage-v8": "4.1.0", "@wdio/cli": "5.16.9", "@wdio/jasmine-framework": "5.16.5", "@wdio/junit-reporter": "5.16.11", @@ -94,19 +95,20 @@ "algoliasearch": "5.1.1", "algoliasearch-v3": "npm:algoliasearch@3.35.0", "algoliasearch-v5": "npm:algoliasearch@5.1.1", - "babel-jest": "27.4.6", "bundlesize": "0.18.0", "doctoc": "1.4.0", "enzyme": "3.11.0", "eslint": "6.8.0", "eslint-plugin-import": "2.24.2", - "jest": "27.4.7", - "jest-diff": "27.4.6", - "jest-environment-jsdom": "27.1.0", - "jest-junit": "12.2.0", - "jest-vue-preprocessor": "1.7.1", - "jest-watch-typeahead": "1.0.0", - "jsdom-global": "3.0.2", + "eslint-plugin-jasmine": "4.1.0", + "eslint-plugin-prettier": "3.4.0", + "eslint-plugin-react": "7.26.0", + "eslint-plugin-react-hooks": "4.3.0", + "eslint-plugin-vitest": "0.5.4", + "eslint-plugin-vue": "9.8.0", + "eslint-plugin-wdio": "5.11.0", + "happy-dom": "20.8.4", + "jsdom": "29.0.0", "lerna": "6.0.3", "patch-package": "6.2.2", "places.js": "1.17.1", @@ -120,8 +122,9 @@ "rollup-plugin-swc3": "0.12.1", "shelljs": "0.8.5", "shipjs": "0.26.0", - "ts-jest": "27", - "typescript": "5.5.2" + "typescript": "5.5.2", + "vite": "^8.0.1", + "vitest": "4.1.0" }, "optionalDependencies": { "oxlint": "1.55.0", diff --git a/packages/algolia-experiences/src/__tests__/get-configuration.test.ts b/packages/algolia-experiences/src/__tests__/get-configuration.test.ts index cd1458c0888..a075b2a4140 100644 --- a/packages/algolia-experiences/src/__tests__/get-configuration.test.ts +++ b/packages/algolia-experiences/src/__tests__/get-configuration.test.ts @@ -9,7 +9,7 @@ describe('fetchConfiguration', () => { }; // @ts-ignore - global.fetch = jest.fn(() => + global.fetch = vi.fn(() => Promise.resolve({ ok: true, json: () => @@ -41,7 +41,7 @@ describe('fetchConfiguration', () => { }; // @ts-ignore - global.fetch = jest.fn(() => + global.fetch = vi.fn(() => Promise.resolve({ ok: true, json: () => diff --git a/packages/algolia-experiences/src/__tests__/get-information.test.ts b/packages/algolia-experiences/src/__tests__/get-information.test.ts index 0d7a9b3ac22..a94d5bfde4c 100644 --- a/packages/algolia-experiences/src/__tests__/get-information.test.ts +++ b/packages/algolia-experiences/src/__tests__/get-information.test.ts @@ -1,5 +1,5 @@ /** - * @jest-environment @instantsearch/testutils/jest-environment-jsdom.ts + * @vitest-environment happy-dom */ import { getElements, getSettings } from '../get-information'; diff --git a/packages/algolia-experiences/src/__tests__/render.test.ts b/packages/algolia-experiences/src/__tests__/render.test.ts index 44e4829231b..857f2687c0b 100644 --- a/packages/algolia-experiences/src/__tests__/render.test.ts +++ b/packages/algolia-experiences/src/__tests__/render.test.ts @@ -1,5 +1,5 @@ /** - * @jest-environment @instantsearch/testutils/jest-environment-jsdom.ts + * @vitest-environment happy-dom */ import { createMultiSearchResponse, @@ -23,7 +23,7 @@ describe('injectStyles', () => { }); describe('configToIndex', () => { - const error = jest.spyOn(console, 'error').mockImplementation(() => {}); + const error = vi.spyOn(console, 'error').mockImplementation(() => {}); beforeEach(() => { error.mockClear(); }); @@ -460,7 +460,7 @@ describe('configToIndex', () => { describe('configure', () => { it('applies configure widget', async () => { const searchClient = createSearchClient({ - search: jest.fn(() => + search: vi.fn(() => Promise.resolve( createMultiSearchResponse({ hits: [ diff --git a/packages/algolia-experiences/src/__tests__/setup-instantsearch.test.ts b/packages/algolia-experiences/src/__tests__/setup-instantsearch.test.ts index c99dba0f040..6711816b123 100644 --- a/packages/algolia-experiences/src/__tests__/setup-instantsearch.test.ts +++ b/packages/algolia-experiences/src/__tests__/setup-instantsearch.test.ts @@ -1,21 +1,21 @@ /** - * @jest-environment @instantsearch/testutils/jest-environment-jsdom.ts + * @vitest-environment happy-dom */ import { castToJestMock, wait } from '@instantsearch/testutils'; import { fetchConfiguration } from '../get-configuration'; import { setupInstantSearch } from '../setup-instantsearch'; -jest.mock('../get-configuration', () => { - const actual = jest.requireActual('../get-configuration'); +vi.mock('../get-configuration', async () => { + const actual = await vi.importActual('../get-configuration'); return { ...actual, - fetchConfiguration: jest.fn(() => Promise.resolve([])), + fetchConfiguration: vi.fn(() => Promise.resolve([])), }; }); describe('setup of InstantSearch', () => { - const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); beforeEach(() => { errorSpy.mockReset(); document.head.innerHTML = ''; diff --git a/packages/algoliasearch-helper/jest.config.js b/packages/algoliasearch-helper/jest.config.js deleted file mode 100644 index 9e932a4e9d3..00000000000 --- a/packages/algoliasearch-helper/jest.config.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -module.exports = { - testEnvironment: 'node', - testMatch: ['/test/spec/**/*.[jt]s?(x)'], - watchPlugins: [ - 'jest-watch-typeahead/filename', - 'jest-watch-typeahead/testname', - ], -}; diff --git a/packages/algoliasearch-helper/jest.setup.js b/packages/algoliasearch-helper/jest.setup.js deleted file mode 100644 index 26cf8e5a2c5..00000000000 --- a/packages/algoliasearch-helper/jest.setup.js +++ /dev/null @@ -1,5 +0,0 @@ -/* eslint-env jest */ - -'use strict'; - -jest.setTimeout(20000); diff --git a/packages/algoliasearch-helper/package.json b/packages/algoliasearch-helper/package.json index a96181001f2..1ad83f051e7 100644 --- a/packages/algoliasearch-helper/package.json +++ b/packages/algoliasearch-helper/package.json @@ -11,8 +11,8 @@ "doc": "node documentation-src/metalsmith.js", "test": "../../scripts/retry.sh 3 'scripts/test.sh'", "test:v4": "../../scripts/retry.sh 3 'scripts/test.sh'", - "test:unit": "jest", - "test:watch": "jest --watch", + "test:unit": "vitest run", + "test:watch": "vitest", "test:v3": "yarn run test", "version": "./scripts/update-version.js", "prepare": "patch-package" @@ -37,7 +37,6 @@ "devDependencies": { "@metalsmith/sass": "1.4.0", "handlebars": "4.1.0", - "jest-watch-typeahead": "0.3.0", "jsdoc-to-markdown": "8.0.0", "metalsmith": "2.5.1", "metalsmith-in-place": "1.4.4", diff --git a/packages/algoliasearch-helper/test/run.js b/packages/algoliasearch-helper/test/run.js index 95ee0b3820f..20e68c4a5bc 100644 --- a/packages/algoliasearch-helper/test/run.js +++ b/packages/algoliasearch-helper/test/run.js @@ -4,33 +4,44 @@ var path = require('path'); var algoliasearch = require('algoliasearch'); algoliasearch = algoliasearch.algoliasearch || algoliasearch; -var jest = require('jest'); - -var staticJestConfig = require('../jest.config'); var enableIntegrationTest = process.env.ONLY_UNIT !== 'true' && process.env.INTEGRATION_TEST_API_KEY && process.env.INTEGRATION_TEST_APPID; -var projectsRootPaths = [path.resolve(__dirname, '..')]; -var dynamicJestConfig = Object.assign({}, staticJestConfig, { - maxWorkers: 4, - setupFilesAfterEnv: staticJestConfig.setupFilesAfterEnv || [], -}); +var include = ['test/spec/**/*.[jt]s?(x)']; +var setupFiles = []; if (enableIntegrationTest) { - dynamicJestConfig.testMatch.push( - '/test/integration-spec/**/*.[jt]s?(x)' - ); - dynamicJestConfig.setupFilesAfterEnv.push( - path.resolve(__dirname, '..', 'jest.setup.js') - ); + include.push('test/integration-spec/**/*.[jt]s?(x)'); + setupFiles.push(path.resolve(__dirname, '..', 'vitest.setup.ts')); } -jest.runCLI(dynamicJestConfig, projectsRootPaths).then(function (response) { - if (!response.results.success) { - process.exitCode = response.globalConfig.testFailureExitCode; +async function run() { + var { startVitest } = await import('vitest/node'); + var vitest = await startVitest('test', [], { + root: path.resolve(__dirname, '..'), + include: include, + setupFiles: setupFiles, + pool: 'threads', + maxWorkers: 4, + watch: false, + }); + + if (!vitest) { + process.exitCode = 1; + return; + } + + var hasFailed = vitest.state.getFiles().some(function (f) { + return f.result && f.result.state === 'fail'; + }); + + await vitest.close(); + + if (hasFailed) { + process.exitCode = 1; } if (enableIntegrationTest) { @@ -59,4 +70,6 @@ jest.runCLI(dynamicJestConfig, projectsRootPaths).then(function (response) { .forEach((n) => client.deleteIndex(n)); }); } -}); +} + +run(); diff --git a/packages/algoliasearch-helper/test/spec/RecommendParameters/methods.js b/packages/algoliasearch-helper/test/spec/RecommendParameters/methods.js index 29eb7c67fed..83ab9f42155 100644 --- a/packages/algoliasearch-helper/test/spec/RecommendParameters/methods.js +++ b/packages/algoliasearch-helper/test/spec/RecommendParameters/methods.js @@ -93,14 +93,14 @@ describe('_buildQueries', () => { var queries = recommendParameters._buildQueries('indexName', {}); expect(queries).toHaveLength(2); expect(queries).toMatchInlineSnapshot(` - Array [ - Object { + [ + { "indexName": "indexName", "model": "bought-together", "objectID": "objectID1", "threshold": 0, }, - Object { + { "facetName": "brand", "indexName": "indexName", "model": "trending-facets", @@ -118,8 +118,8 @@ describe('_buildQueries', () => { var queries = recommendParameters._buildQueries('indexName', {}); expect(queries).toHaveLength(1); expect(queries).toMatchInlineSnapshot(` - Array [ - Object { + [ + { "indexName": "indexName", "model": "bought-together", "objectID": "objectID1", diff --git a/packages/algoliasearch-helper/test/spec/SearchParameters/constructorFn.js b/packages/algoliasearch-helper/test/spec/SearchParameters/constructorFn.js index 7a51dbec12d..7435f3ebb65 100644 --- a/packages/algoliasearch-helper/test/spec/SearchParameters/constructorFn.js +++ b/packages/algoliasearch-helper/test/spec/SearchParameters/constructorFn.js @@ -56,7 +56,7 @@ test('Constructor should ignore keys with undefined values', function () { test('Constructor should warn about invalid userToken', function () { const message = '[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}'; - console.warn = jest.fn(); + console.warn = vi.fn(); var sp1 = new SearchParameters({ userToken: '', @@ -134,7 +134,7 @@ test('Factory should ignore keys with undefined values', function () { test('Factory should warn about invalid userToken', function () { const message = '[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}'; - console.warn = jest.fn(); + console.warn = vi.fn(); SearchParameters.make({ userToken: null }); expect(console.warn).toHaveBeenCalledTimes(1); diff --git a/packages/algoliasearch-helper/test/spec/SearchParameters/setQueryParameter.js b/packages/algoliasearch-helper/test/spec/SearchParameters/setQueryParameter.js index bbb7684f1a7..a1b2f174af2 100644 --- a/packages/algoliasearch-helper/test/spec/SearchParameters/setQueryParameter.js +++ b/packages/algoliasearch-helper/test/spec/SearchParameters/setQueryParameter.js @@ -48,7 +48,7 @@ test('setQueryParameter should not throw an error when trying to add an unknown test('setQueryParameter should warn about invalid userToken', function () { const message = '[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}'; - console.warn = jest.fn(); + console.warn = vi.fn(); var state = new SearchParameters(); state.setQueryParameter('userToken', null); diff --git a/packages/algoliasearch-helper/test/spec/SearchParameters/setQueryParameters.js b/packages/algoliasearch-helper/test/spec/SearchParameters/setQueryParameters.js index d43cf211fef..721fcb97682 100644 --- a/packages/algoliasearch-helper/test/spec/SearchParameters/setQueryParameters.js +++ b/packages/algoliasearch-helper/test/spec/SearchParameters/setQueryParameters.js @@ -97,7 +97,7 @@ test('setQueryParameters should omit defined parameters with next values of unde test('setQueryParameters should warn about invalid userToken', function () { const message = '[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}'; - console.warn = jest.fn(); + console.warn = vi.fn(); var state = new SearchParameters(); state.setQueryParameters({ userToken: null }); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/client.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/client.js index c4b79014e7f..5b043932228 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/client.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/client.js @@ -9,7 +9,7 @@ var version = require('../../../src/version'); function makeFakeClient() { var client = algoliasearch('what', 'wait', {}); - client.search = jest.fn(function () { + client.search = vi.fn(function () { return new Promise(function () {}); }); @@ -34,7 +34,7 @@ test("client without addAlgoliaAgent() doesn't throw on instantiation", function test('addAlgoliaAgent gets called if exists', function () { var client = { - addAlgoliaAgent: jest.fn(), + addAlgoliaAgent: vi.fn(), }; expect(client.addAlgoliaAgent).not.toHaveBeenCalled(); @@ -55,7 +55,7 @@ test("client without clearCache() doesn't throw when clearing cache", function ( test('clearCache gets called if exists', function () { var client = { - clearCache: jest.fn(), + clearCache: vi.fn(), }; var helper = algoliaSearchHelper(client); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/detach.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/detach.js index ae6471d90aa..45592d435d2 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/detach.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/detach.js @@ -2,33 +2,35 @@ var algoliasearchHelper = require('../../../../'); -test('[derived helper] detach a derived helper', function (done) { - var client = { - search: searchTest, - }; - var helper = algoliasearchHelper(client, 'indexName'); - var derivedHelper = helper.derive(function (s) { - return s; - }); - derivedHelper.on('result', function () {}); - helper.search(); - derivedHelper.detach(); - helper.search(); +test('[derived helper] detach a derived helper', function () { + return new Promise(function (done) { + var client = { + search: searchTest, + }; + var helper = algoliasearchHelper(client, 'indexName'); + var derivedHelper = helper.derive(function (s) { + return s; + }); + derivedHelper.on('result', function () {}); + helper.search(); + derivedHelper.detach(); + helper.search(); - var nbRequest; - function searchTest(requests) { - nbRequest = nbRequest || 0; - if (nbRequest === 0) { - expect(requests.length).toBe(2); - expect(requests[0]).toEqual(requests[1]); - expect(derivedHelper.listeners('result').length).toBe(1); - nbRequest++; - } else if (nbRequest === 1) { - expect(requests.length).toBe(1); - expect(derivedHelper.listeners('result').length).toBe(0); - done(); - } + var nbRequest; + function searchTest(requests) { + nbRequest = nbRequest || 0; + if (nbRequest === 0) { + expect(requests.length).toBe(2); + expect(requests[0]).toEqual(requests[1]); + expect(derivedHelper.listeners('result').length).toBe(1); + nbRequest++; + } else if (nbRequest === 1) { + expect(requests.length).toBe(1); + expect(derivedHelper.listeners('result').length).toBe(0); + done(); + } - return new Promise(function () {}); - } + return new Promise(function () {}); + } + }); }); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/empty-index.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/empty-index.js index 8805d04df1b..0017eb7e95f 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/empty-index.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/empty-index.js @@ -5,7 +5,7 @@ var algoliasearchHelper = require('../../../../'); describe('searches', function () { test('calls client.search for each derived helper that has an index', function () { var client = { - search: jest.fn(function (requests) { + search: vi.fn(function (requests) { return Promise.resolve({ results: requests.map(function () { return { hits: [] }; @@ -34,7 +34,7 @@ describe('searches', function () { test('does not call client.search if all indices are empty', function () { var client = { - search: jest.fn(function (requests) { + search: vi.fn(function (requests) { return Promise.resolve({ results: requests.map(function () { return { hits: [] }; @@ -57,7 +57,7 @@ describe('searches', function () { test('does not call client.search if no derived helpers', function () { var client = { - search: jest.fn(function (requests) { + search: vi.fn(function (requests) { return Promise.resolve({ results: requests.map(function () { return { hits: [] }; @@ -76,7 +76,7 @@ describe('searches', function () { describe('lastResults', function () { test('gives a result for each derived helper that has an index', function () { var client = { - search: jest.fn(function (requests) { + search: vi.fn(function (requests) { return Promise.resolve({ results: requests.map(function () { return { hits: [] }; @@ -109,7 +109,7 @@ describe('lastResults', function () { describe('result event', function () { test('gives a result event for each derived helper', function () { var client = { - search: jest.fn(function (requests) { + search: vi.fn(function (requests) { return Promise.resolve({ results: requests.map(function () { return { hits: [] }; @@ -119,13 +119,13 @@ describe('result event', function () { }; var helper = algoliasearchHelper(client, 'indexName'); - var derivedResultSpy1 = jest.fn(); + var derivedResultSpy1 = vi.fn(); helper .derive(function (state) { return state.setIndex('indexName'); }) .on('result', derivedResultSpy1); - var derivedResultSpy2 = jest.fn(); + var derivedResultSpy2 = vi.fn(); helper .derive(function (state) { return state.setIndex(''); @@ -152,7 +152,7 @@ describe('result event', function () { test('gives a result event for each derived helper when no query is done', function () { var client = { - search: jest.fn(function (requests) { + search: vi.fn(function (requests) { return Promise.resolve({ results: requests.map(function () { return { hits: [] }; @@ -162,7 +162,7 @@ describe('result event', function () { }; var helper = algoliasearchHelper(client, 'indexName'); - var derivedResultSpy1 = jest.fn(); + var derivedResultSpy1 = vi.fn(); helper .derive(function (state) { return state.setIndex(''); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/events.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/events.js index c3773846d45..eaf16ad0269 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/events.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/derive/events.js @@ -4,20 +4,20 @@ var algoliasearchHelper = require('../../../../'); function makeFakeClient() { return { - search: jest.fn(function () { + search: vi.fn(function () { return new Promise(function () {}); }), - searchForFacetValues: jest.fn(function () { + searchForFacetValues: vi.fn(function () { return new Promise(function () {}); }), - getRecommendations: jest.fn(function () { + getRecommendations: vi.fn(function () { return new Promise(function () {}); }), }; } test('[derived helper] emit a search event', function () { - var searched = jest.fn(); + var searched = vi.fn(); var client = makeFakeClient(); var helper = algoliasearchHelper(client, 'index'); var derivedHelper = helper.derive(function (s) { @@ -38,7 +38,7 @@ test('[derived helper] emit a search event', function () { }); test('[derived helper] emit a fetch event', function () { - var fetched = jest.fn(); + var fetched = vi.fn(); var client = makeFakeClient(); var helper = algoliasearchHelper(client, 'index'); var derivedHelper = helper.derive( diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/events.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/events.js index 737410a1dbc..67e1a39e924 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/events.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/events.js @@ -4,10 +4,10 @@ var algoliaSearchHelper = require('../../../index'); function makeFakeClient() { return { - search: jest.fn(function () { + search: vi.fn(function () { return new Promise(function () {}); }), - searchForFacetValues: jest.fn(function () { + searchForFacetValues: vi.fn(function () { return new Promise(function () {}); }), }; @@ -18,7 +18,7 @@ function runAllMicroTasks() { } test('Change events should be emitted with reset page to true on implicit reset methods', function () { - var changed = jest.fn(); + var changed = vi.fn(); var fakeClient = makeFakeClient(); var helper = algoliaSearchHelper(fakeClient, 'Index'); @@ -48,7 +48,7 @@ test('Change events should be emitted with reset page to true on implicit reset }); test('Change events should be emitted with reset page to false on regular methods', function () { - var changed = jest.fn(); + var changed = vi.fn(); var fakeClient = makeFakeClient(); var helper = algoliaSearchHelper(fakeClient, 'Index'); @@ -210,7 +210,7 @@ test('Change events should only be emitted for meaningful changes', function () }); test('search event should be emitted once when the search is triggered and before the request is sent', function () { - var searched = jest.fn(); + var searched = vi.fn(); var fakeClient = makeFakeClient(); var helper = algoliaSearchHelper(fakeClient, 'Index', { disjunctiveFacets: ['city'], @@ -261,7 +261,7 @@ test('search event should be emitted once when the search is triggered and befor }); test('searchOnce event should be emitted once when the search is triggered using searchOnce and before the request is sent', function () { - var searchedOnce = jest.fn(); + var searchedOnce = vi.fn(); var fakeClient = makeFakeClient(); var helper = algoliaSearchHelper(fakeClient, 'Index', { disjunctiveFacets: ['city'], @@ -287,7 +287,7 @@ test( 'searchForFacetValues event should be emitted once when the search is triggered using' + ' searchForFacetValues and before the request is sent', function () { - var searchedForFacetValues = jest.fn(); + var searchedForFacetValues = vi.fn(); var fakeClient = makeFakeClient(); var helper = algoliaSearchHelper(fakeClient, 'Index', { disjunctiveFacets: ['city'], @@ -311,7 +311,7 @@ test( ); test('result event should be emitted once the request is complete', function () { - var resulted = jest.fn(); + var resulted = vi.fn(); var fakeClient = makeFakeClient(); var helper = algoliaSearchHelper(fakeClient, 'Index', { disjunctiveFacets: ['city'], @@ -340,7 +340,7 @@ test('result event should be emitted once the request is complete', function () }); test('error event should be emitted once the request is complete with errors', function () { - var errored = jest.fn(); + var errored = vi.fn(); var fakeClient = makeFakeClient(); var helper = algoliaSearchHelper(fakeClient, 'Index', { disjunctiveFacets: ['city'], @@ -366,7 +366,7 @@ test('error event should be emitted once the request is complete with errors', f }); test('error event should be emitted if an error happens at request time', function () { - var errored = jest.fn(); + var errored = vi.fn(); var fakeClient = makeFakeClient(); var helper = algoliaSearchHelper(fakeClient, 'Index', { disjunctiveFacets: ['city'], diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/excludes.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/excludes.js index ec533eb8f70..955f3a38b58 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/excludes.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/excludes.js @@ -22,28 +22,30 @@ test('addExclude should add an exclusion', function () { ).toBeTruthy(); }); -test('removeExclude should remove an exclusion', function (done) { - var helper = algoliasearchHelper(fakeClient, null, { - facets: ['facet'], - }); +test('removeExclude should remove an exclusion', function () { + return new Promise(function (done) { + var helper = algoliasearchHelper(fakeClient, null, { + facets: ['facet'], + }); - helper._search = function () {}; + helper._search = function () {}; - var facetName = 'facet'; - var facetValueToExclude = 'brand'; + var facetName = 'facet'; + var facetValueToExclude = 'brand'; - helper.addExclude(facetName, facetValueToExclude); - expect(helper.state.facetsExcludes[facetName].length === 1).toBeTruthy(); - helper.removeExclude(facetName, facetValueToExclude); - expect(helper.state.facetsExcludes[facetName]).toEqual([]); - - try { + helper.addExclude(facetName, facetValueToExclude); + expect(helper.state.facetsExcludes[facetName].length === 1).toBeTruthy(); helper.removeExclude(facetName, facetValueToExclude); - } catch (e) { - done(new Error('Removing unset exclusions should be ok...')); - } + expect(helper.state.facetsExcludes[facetName]).toEqual([]); - done(); + try { + helper.removeExclude(facetName, facetValueToExclude); + } catch (e) { + done(new Error('Removing unset exclusions should be ok...')); + } + + done(); + }); }); test('isExcluded should allow to omit the value', function () { diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/findAnswers.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/findAnswers.js index fe5d20fc0ad..edeb5408f06 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/findAnswers.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/findAnswers.js @@ -11,7 +11,7 @@ function makeFakeFindAnswersResponse() { } function setupTestEnvironment(helperOptions) { - var findAnswers = jest.fn(function () { + var findAnswers = vi.fn(function () { return Promise.resolve([makeFakeFindAnswersResponse()]); }); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/numericFilters.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/numericFilters.js index d91785cef86..9c3fad5facb 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/numericFilters.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/numericFilters.js @@ -7,71 +7,75 @@ var algoliasearchHelper = require('../../../index'); var fakeClient = {}; -test('Numeric filters: numeric filters from constructor', function (done) { - var client = algoliasearch('dsf', 'dsfdf'); - - client.search = function (queries) { - var ps = queries[0].params; - - expect(ps.numericFilters).toEqual([ - 'attribute1>3', - 'attribute1<=100', - 'attribute2=42', - 'attribute2=25', - 'attribute2=58', - ['attribute2=27', 'attribute2=70'], - ]); - - done(); - - return new Promise(function () {}); - }; - - var helper = algoliasearchHelper(client, 'index', { - numericRefinements: { - attribute1: { - '>': [3], - '<=': [100], +test('Numeric filters: numeric filters from constructor', function () { + return new Promise(function (done) { + var client = algoliasearch('dsf', 'dsfdf'); + + client.search = function (queries) { + var ps = queries[0].params; + + expect(ps.numericFilters).toEqual([ + 'attribute1>3', + 'attribute1<=100', + 'attribute2=42', + 'attribute2=25', + 'attribute2=58', + ['attribute2=27', 'attribute2=70'], + ]); + + done(); + + return new Promise(function () {}); + }; + + var helper = algoliasearchHelper(client, 'index', { + numericRefinements: { + attribute1: { + '>': [3], + '<=': [100], + }, + attribute2: { + '=': [42, 25, 58, [27, 70]], + }, }, - attribute2: { - '=': [42, 25, 58, [27, 70]], - }, - }, - }); + }); - helper.search(); + helper.search(); + }); }); -test('Numeric filters: numeric filters from setters', function (done) { - var client = algoliasearch('dsf', 'dsfdf'); +test('Numeric filters: numeric filters from setters', function () { + return new Promise(function (done) { + var client = algoliasearch('dsf', 'dsfdf'); - client.search = function (queries) { - var ps = queries[0].params; + client.search = function (queries) { + var ps = queries[0].params; - expect(ps.numericFilters).toEqual([ - 'attribute1>3', - 'attribute1<=100', - 'attribute2=42', - 'attribute2=25', - 'attribute2=58', - ['attribute2=27', 'attribute2=70'], - ]); + expect(ps.numericFilters).toEqual([ + 'attribute1>3', + 'attribute1<=100', + 'attribute2=42', + 'attribute2=25', + 'attribute2=58', + ['attribute2=27', 'attribute2=70'], + ]); - done(); + done(); - return new Promise(function () {}); - }; + return new Promise(function () {}); + }; - var helper = algoliasearchHelper(client, 'index'); + var helper = algoliasearchHelper(client, 'index'); - helper.addNumericRefinement('attribute1', '>', 3); - helper.addNumericRefinement('attribute1', '<=', 100); - helper.addNumericRefinement('attribute2', '=', 42); - helper.addNumericRefinement('attribute2', '=', 25); - helper.addNumericRefinement('attribute2', '=', 58); - helper.addNumericRefinement('attribute2', '=', [27, 70]); + helper.addNumericRefinement('attribute1', '>', 3); + helper.addNumericRefinement('attribute1', '<=', 100); + helper.addNumericRefinement('attribute2', '=', 42); + helper.addNumericRefinement('attribute2', '=', 25); + helper.addNumericRefinement('attribute2', '=', 58); + helper.addNumericRefinement('attribute2', '=', [27, 70]); - helper.search(); + helper.search(); + }); }); test('Should be able to remove values one by one even 0s', function () { diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/pendingSearch.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/pendingSearch.js index 00018aa06a2..fe1c0d68964 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/pendingSearch.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/pendingSearch.js @@ -6,87 +6,16 @@ algoliasearch = algoliasearch.algoliasearch || algoliasearch; var algoliasearchHelper = require('../../../index'); -test('When searchOnce with callback, hasPendingRequests is true', function (done) { - var testData = require('../../datasets/SearchParameters/search.dataset')(); - var client = algoliasearch('dsf', 'dsfdf'); - - var triggerCb; - client.search = function () { - return new Promise(function (resolve) { - triggerCb = function () { - resolve(testData.response); - }; - }); - }; - - var helper = algoliasearchHelper(client, 'test_hotels-node'); - var countNoMoreSearch = 0; - helper.on('searchQueueEmpty', function () { - countNoMoreSearch += 1; - }); - - expect(helper.hasPendingRequests()).toBe(false); - - helper.searchOnce(helper.state, function () { - expect(helper.hasPendingRequests()).toBe(false); - expect(countNoMoreSearch).toBe(1); - done(); - }); - - expect(helper.hasPendingRequests()).toBe(true); - expect(countNoMoreSearch).toBe(0); - - triggerCb(); -}); - -test('When searchOnce with promises, hasPendingRequests is true', function (done) { - var testData = require('../../datasets/SearchParameters/search.dataset')(); - var client = algoliasearch('dsf', 'dsfdf'); - - var triggerCb; - client.search = function () { - return new Promise(function (resolve) { - triggerCb = function () { - resolve(testData.response); - }; - }); - }; - - var helper = algoliasearchHelper(client, 'test_hotels-node'); - var countNoMoreSearch = 0; - helper.on('searchQueueEmpty', function () { - countNoMoreSearch += 1; - }); - - expect(helper.hasPendingRequests()).toBe(false); - - helper.searchOnce(helper.state).then(function () { - expect(helper.hasPendingRequests()).toBe(false); - expect(countNoMoreSearch).toBe(1); - done(); - }); - - expect(helper.hasPendingRequests()).toBe(true); - expect(countNoMoreSearch).toBe(0); - - triggerCb(); -}); - -if (!isV5) { - test('When searchForFacetValues, hasPendingRequests is true (v3, v4)', function (done) { +test('When searchOnce with callback, hasPendingRequests is true', function () { + return new Promise(function (done) { + var testData = require('../../datasets/SearchParameters/search.dataset')(); var client = algoliasearch('dsf', 'dsfdf'); - let triggerCb; - client.searchForFacetValues = function () { + var triggerCb; + client.search = function () { return new Promise(function (resolve) { triggerCb = function () { - resolve([ - { - exhaustiveFacetsCount: true, - facetHits: [], - processingTimeMS: 3, - }, - ]); + resolve(testData.response); }; }); }; @@ -99,7 +28,7 @@ if (!isV5) { expect(helper.hasPendingRequests()).toBe(false); - helper.searchForFacetValues('').then(function () { + helper.searchOnce(helper.state, function () { expect(helper.hasPendingRequests()).toBe(false); expect(countNoMoreSearch).toBe(1); done(); @@ -110,23 +39,18 @@ if (!isV5) { triggerCb(); }); -} else { - test('When searchForFacetValues, hasPendingRequests is true (v5)', function (done) { +}); + +test('When searchOnce with promises, hasPendingRequests is true', function () { + return new Promise(function (done) { + var testData = require('../../datasets/SearchParameters/search.dataset')(); var client = algoliasearch('dsf', 'dsfdf'); - let triggerCb; + var triggerCb; client.search = function () { return new Promise(function (resolve) { triggerCb = function () { - resolve({ - results: [ - { - exhaustiveFacetsCount: true, - facetHits: [], - processingTimeMS: 3, - }, - ], - }); + resolve(testData.response); }; }); }; @@ -139,7 +63,7 @@ if (!isV5) { expect(helper.hasPendingRequests()).toBe(false); - helper.searchForFacetValues('').then(function () { + helper.searchOnce(helper.state).then(function () { expect(helper.hasPendingRequests()).toBe(false); expect(countNoMoreSearch).toBe(1); done(); @@ -150,98 +74,186 @@ if (!isV5) { triggerCb(); }); -} - -test('When helper.search(), hasPendingRequests is true', function (done) { - var testData = require('../../datasets/SearchParameters/search.dataset')(); - var client = algoliasearch('dsf', 'dsfdf'); +}); - var triggerCb; - client.search = function () { - return new Promise(function (resolve) { - triggerCb = function () { - resolve(testData.response); +if (!isV5) { + test('When searchForFacetValues, hasPendingRequests is true (v3, v4)', function () { + return new Promise(function (done) { + var client = algoliasearch('dsf', 'dsfdf'); + + let triggerCb; + client.searchForFacetValues = function () { + return new Promise(function (resolve) { + triggerCb = function () { + resolve([ + { + exhaustiveFacetsCount: true, + facetHits: [], + processingTimeMS: 3, + }, + ]); + }; + }); }; - }); - }; - var helper = algoliasearchHelper(client, 'test_hotels-node'); - var countNoMoreSearch = 0; - helper.on('searchQueueEmpty', function () { - countNoMoreSearch += 1; - }); + var helper = algoliasearchHelper(client, 'test_hotels-node'); + var countNoMoreSearch = 0; + helper.on('searchQueueEmpty', function () { + countNoMoreSearch += 1; + }); - expect(helper.hasPendingRequests()).toBe(false); + expect(helper.hasPendingRequests()).toBe(false); - helper.on('result', function () { - expect(helper.hasPendingRequests()).toBe(false); - expect(countNoMoreSearch).toBe(1); - done(); + helper.searchForFacetValues('').then(function () { + expect(helper.hasPendingRequests()).toBe(false); + expect(countNoMoreSearch).toBe(1); + done(); + }); + + expect(helper.hasPendingRequests()).toBe(true); + expect(countNoMoreSearch).toBe(0); + + triggerCb(); + }); }); +} else { + test('When searchForFacetValues, hasPendingRequests is true (v5)', function () { + return new Promise(function (done) { + var client = algoliasearch('dsf', 'dsfdf'); + + let triggerCb; + client.search = function () { + return new Promise(function (resolve) { + triggerCb = function () { + resolve({ + results: [ + { + exhaustiveFacetsCount: true, + facetHits: [], + processingTimeMS: 3, + }, + ], + }); + }; + }); + }; + + var helper = algoliasearchHelper(client, 'test_hotels-node'); + var countNoMoreSearch = 0; + helper.on('searchQueueEmpty', function () { + countNoMoreSearch += 1; + }); - helper.search(); + expect(helper.hasPendingRequests()).toBe(false); + + helper.searchForFacetValues('').then(function () { + expect(helper.hasPendingRequests()).toBe(false); + expect(countNoMoreSearch).toBe(1); + done(); + }); - expect(helper.hasPendingRequests()).toBe(true); - expect(countNoMoreSearch).toBe(0); + expect(helper.hasPendingRequests()).toBe(true); + expect(countNoMoreSearch).toBe(0); - triggerCb(); -}); + triggerCb(); + }); + }); +} -test('When helper.search() and one request is discarded, hasPendingRequests is true unless all come back', function (done) { - var testData = require('../../datasets/SearchParameters/search.dataset')(); - var client = algoliasearch('dsf', 'dsfdf'); +test('When helper.search(), hasPendingRequests is true', function () { + return new Promise(function (done) { + var testData = require('../../datasets/SearchParameters/search.dataset')(); + var client = algoliasearch('dsf', 'dsfdf'); - var triggerCbs = []; - client.search = function () { - return new Promise(function (resolve) { - triggerCbs.push(function () { - resolve(testData.response); + var triggerCb; + client.search = function () { + return new Promise(function (resolve) { + triggerCb = function () { + resolve(testData.response); + }; }); + }; + + var helper = algoliasearchHelper(client, 'test_hotels-node'); + var countNoMoreSearch = 0; + helper.on('searchQueueEmpty', function () { + countNoMoreSearch += 1; }); - }; - var helper = algoliasearchHelper(client, 'test_hotels-node'); - var countNoMoreSearch = 0; - helper.on('searchQueueEmpty', function () { - countNoMoreSearch += 1; - }); + expect(helper.hasPendingRequests()).toBe(false); - expect(helper.hasPendingRequests()).toBe(false); + helper.on('result', function () { + expect(helper.hasPendingRequests()).toBe(false); + expect(countNoMoreSearch).toBe(1); + done(); + }); - helper.search(); - helper.search(); - helper.search(); + helper.search(); - // intermediary result handler - helper.once('result', function () { expect(helper.hasPendingRequests()).toBe(true); expect(countNoMoreSearch).toBe(0); + + triggerCb(); }); +}); - // The second search returns from algolia -> discards the first one - triggerCbs[1](); +test('When helper.search() and one request is discarded, hasPendingRequests is true unless all come back', function () { + return new Promise(function (done) { + var testData = require('../../datasets/SearchParameters/search.dataset')(); + var client = algoliasearch('dsf', 'dsfdf'); - // Final result handler - helper.once('result', function () { - expect(helper.hasPendingRequests()).toBe(true); - expect(countNoMoreSearch).toBe(0); - }); + var triggerCbs = []; + client.search = function () { + return new Promise(function (resolve) { + triggerCbs.push(function () { + resolve(testData.response); + }); + }); + }; + + var helper = algoliasearchHelper(client, 'test_hotels-node'); + var countNoMoreSearch = 0; + helper.on('searchQueueEmpty', function () { + countNoMoreSearch += 1; + }); - helper.searchOnce({}, function () { expect(helper.hasPendingRequests()).toBe(false); - expect(countNoMoreSearch).toBe(1); - }); - // The third search returns from Algolia - triggerCbs[2](); - // The searchOnce should not be impacted - triggerCbs[3](); - triggerCbs[0](); - // this will be ignored and it won't change anything + helper.search(); + helper.search(); + helper.search(); - setTimeout(function () { - expect(helper.hasPendingRequests()).toBe(false); - expect(countNoMoreSearch).toBe(1); - done(); - }, 0); + // intermediary result handler + helper.once('result', function () { + expect(helper.hasPendingRequests()).toBe(true); + expect(countNoMoreSearch).toBe(0); + }); + + // The second search returns from algolia -> discards the first one + triggerCbs[1](); + + // Final result handler + helper.once('result', function () { + expect(helper.hasPendingRequests()).toBe(true); + expect(countNoMoreSearch).toBe(0); + }); + + helper.searchOnce({}, function () { + expect(helper.hasPendingRequests()).toBe(false); + expect(countNoMoreSearch).toBe(1); + }); + + // The third search returns from Algolia + triggerCbs[2](); + // The searchOnce should not be impacted + triggerCbs[3](); + triggerCbs[0](); + // this will be ignored and it won't change anything + + setTimeout(function () { + expect(helper.hasPendingRequests()).toBe(false); + expect(countNoMoreSearch).toBe(1); + done(); + }, 0); + }); }); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/queryID.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/queryID.js index e9c3dcf6b9f..c2445524617 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/queryID.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/queryID.js @@ -21,75 +21,79 @@ test('the queryid should keep increasing when new requests arrives', function () expect(helper._queryId).toBe(initialQueryID); }); -test('the response handler should check that the query is not outdated', function (done) { - var testData = require('../../datasets/SearchParameters/search.dataset')(); - var shouldTriggerResult = true; - var callCount = 0; - - var helper = algoliasearchHelper(fakeClient, null, {}); - - helper.on('result', function () { - callCount++; - - if (!shouldTriggerResult) { - done(new Error('The id was outdated')); - } +test('the response handler should check that the query is not outdated', function () { + return new Promise(function (done) { + var testData = require('../../datasets/SearchParameters/search.dataset')(); + var shouldTriggerResult = true; + var callCount = 0; + + var helper = algoliasearchHelper(fakeClient, null, {}); + + helper.on('result', function () { + callCount++; + + if (!shouldTriggerResult) { + done(new Error('The id was outdated')); + } + }); + + var states = [ + { + state: helper.state, + queriesCount: 1, + helper: helper, + }, + ]; + + helper._dispatchAlgoliaResponse( + states, + helper._lastQueryIdReceived + 1, + testData.response + ); + helper._dispatchAlgoliaResponse( + states, + helper._lastQueryIdReceived + 10, + testData.response + ); + expect(callCount).toBe(2); + + shouldTriggerResult = false; + + helper._dispatchAlgoliaResponse( + states, + helper._lastQueryIdReceived - 1, + testData.response + ); + expect(callCount).toBe(2); + + done(); }); - - var states = [ - { - state: helper.state, - queriesCount: 1, - helper: helper, - }, - ]; - - helper._dispatchAlgoliaResponse( - states, - helper._lastQueryIdReceived + 1, - testData.response - ); - helper._dispatchAlgoliaResponse( - states, - helper._lastQueryIdReceived + 10, - testData.response - ); - expect(callCount).toBe(2); - - shouldTriggerResult = false; - - helper._dispatchAlgoliaResponse( - states, - helper._lastQueryIdReceived - 1, - testData.response - ); - expect(callCount).toBe(2); - - done(); }); -test('the error handler should check that the query is not outdated', function (done) { - var shouldTriggerError = true; - var callCount = 0; +test('the error handler should check that the query is not outdated', function () { + return new Promise(function (done) { + var shouldTriggerError = true; + var callCount = 0; - var helper = algoliasearchHelper(fakeClient, null, {}); + var helper = algoliasearchHelper(fakeClient, null, {}); - helper.on('error', function () { - callCount++; + helper.on('error', function () { + callCount++; - if (!shouldTriggerError) { - done(new Error('The id was outdated')); - } - }); + if (!shouldTriggerError) { + done(new Error('The id was outdated')); + } + }); - helper._dispatchAlgoliaError(helper._lastQueryIdReceived + 1, new Error()); - helper._dispatchAlgoliaError(helper._lastQueryIdReceived + 10, new Error()); - expect(callCount).toBe(2); + helper._dispatchAlgoliaError(helper._lastQueryIdReceived + 1, new Error()); + helper._dispatchAlgoliaError(helper._lastQueryIdReceived + 10, new Error()); + expect(callCount).toBe(2); - shouldTriggerError = false; + shouldTriggerError = false; - helper._dispatchAlgoliaError(helper._lastQueryIdReceived - 1, new Error()); - expect(callCount).toBe(2); + helper._dispatchAlgoliaError(helper._lastQueryIdReceived - 1, new Error()); + expect(callCount).toBe(2); - done(); + done(); + }); }); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/recommendState.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/recommendState.js index 44088370f75..b53cfae5aad 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/recommendState.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/recommendState.js @@ -26,20 +26,21 @@ describe('_recommendChange', () => { expect(helper.recommendState.params).toEqual([params1, params2]); }); - test('triggers a change event', (done) => { - var params = { $$id: '1', objectID: 'objectID1', model: 'bought-together' }; - var helper = algoliasearchHelper({}, null, {}); + test('triggers a change event', function () { + return new Promise(function (done) { + var params = { $$id: '1', objectID: 'objectID1', model: 'bought-together' }; + var helper = algoliasearchHelper({}, null, {}); - // eslint-disable-next-line no-warning-comments - // TODO: listen to "change" event when events for Recommend are implemented - helper.on('recommend:change', (event) => { - var recommendState = event.recommend.state; - expect(recommendState).toEqual(helper.recommendState); - done(); - }); + // TODO: listen to "change" event when events for Recommend are implemented + helper.on('recommend:change', (event) => { + var recommendState = event.recommend.state; + expect(recommendState).toEqual(helper.recommendState); + done(); + }); - helper._recommendChange({ - state: helper.recommendState.addParams(params), + helper._recommendChange({ + state: helper.recommendState.addParams(params), + }); }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/searchForFacetValues.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/searchForFacetValues.js index 0f1a367a7ad..ebd298d09e9 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/searchForFacetValues.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/searchForFacetValues.js @@ -11,11 +11,11 @@ function makeFakeSearchForFacetValuesResponse() { } test('searchForFacetValues calls the client method over the index method', function () { - var clientSearchForFacetValues = jest.fn(function () { + var clientSearchForFacetValues = vi.fn(function () { return Promise.resolve([makeFakeSearchForFacetValuesResponse()]); }); - var indexSearchForFacetValues = jest.fn(function () { + var indexSearchForFacetValues = vi.fn(function () { return Promise.resolve(makeFakeSearchForFacetValuesResponse()); }); @@ -37,7 +37,7 @@ test('searchForFacetValues calls the client method over the index method', funct }); test('searchForFacetValues calls the index method if no client method', function () { - var indexSearchForFacetValues = jest.fn(function () { + var indexSearchForFacetValues = vi.fn(function () { return Promise.resolve(makeFakeSearchForFacetValuesResponse()); }); @@ -57,15 +57,15 @@ test('searchForFacetValues calls the index method if no client method', function }); test('searchForFacetValues calls client.search if client.searchForFacets exists', function () { - var clientSearch = jest.fn(function () { + var clientSearch = vi.fn(function () { return Promise.resolve({ results: [makeFakeSearchForFacetValuesResponse()], }); }); var fakeClient = { - searchForFacets: jest.fn(), - searchForFacetValues: jest.fn(), + searchForFacets: vi.fn(), + searchForFacetValues: vi.fn(), search: clientSearch, }; @@ -119,7 +119,7 @@ test('searchForFacetValues resolve with the correct response from initIndex', fu }); test('index.searchForFacetValues should search for facetValues with the current state', function () { - var indexSearchForFacetValues = jest.fn(function () { + var indexSearchForFacetValues = vi.fn(function () { return Promise.resolve(makeFakeSearchForFacetValuesResponse()); }); @@ -149,7 +149,7 @@ test('index.searchForFacetValues should search for facetValues with the current }); test('index.searchForFacetValues can override the current search state', function () { - var indexSearchForFacetValues = jest.fn(function () { + var indexSearchForFacetValues = vi.fn(function () { return Promise.resolve(makeFakeSearchForFacetValuesResponse()); }); @@ -182,7 +182,7 @@ test('index.searchForFacetValues can override the current search state', functio }); test('client.searchForFacetValues should search for facetValues with the current state', function () { - var clientSearchForFacetValues = jest.fn(function () { + var clientSearchForFacetValues = vi.fn(function () { return Promise.resolve([makeFakeSearchForFacetValuesResponse()]); }); @@ -209,7 +209,7 @@ test('client.searchForFacetValues should search for facetValues with the current }); test('client.searchForFacetValues can override the current search state', function () { - var clientSearchForFacetValues = jest.fn(function () { + var clientSearchForFacetValues = vi.fn(function () { return Promise.resolve([makeFakeSearchForFacetValuesResponse()]); }); @@ -239,7 +239,7 @@ test('client.searchForFacetValues can override the current search state', functi }); test('client.search should search for facetValues with the current state', function () { - var clientSearch = jest.fn(function () { + var clientSearch = vi.fn(function () { return Promise.resolve({ results: [makeFakeSearchForFacetValuesResponse()], }); @@ -269,7 +269,7 @@ test('client.search should search for facetValues with the current state', funct }); test('client.search can override the current search state', function () { - var clientSearch = jest.fn(function () { + var clientSearch = vi.fn(function () { return Promise.resolve({ results: [makeFakeSearchForFacetValuesResponse()], }); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/searchOnce.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/searchOnce.js index 0d9e5141ca2..0b89c0ce2b2 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/searchOnce.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/searchOnce.js @@ -3,123 +3,127 @@ var algoliasearchHelper = require('../../../index'); var SearchParameters = require('../../../src/SearchParameters'); -test('searchOnce should call the algolia client according to the number of refinements and call callback with no error and with results when no error', function (done) { - var testData = require('../../datasets/SearchParameters/search.dataset')(); - - var client = { - search: jest.fn().mockImplementationOnce(function () { - return Promise.resolve(testData.response); - }), - }; - - var helper = algoliasearchHelper(client, 'test_hotels-node'); - - var parameters = new SearchParameters({ - disjunctiveFacets: ['city'], - }) - .setIndex('test_hotels-node') - .addDisjunctiveFacetRefinement('city', 'Paris') - .addDisjunctiveFacetRefinement('city', 'New York'); - - helper.searchOnce(parameters, function (err, data) { - expect(err).toBe(null); - - // shame deepclone, to remove any associated methods coming from the results - expect(JSON.parse(JSON.stringify(data))).toEqual( - JSON.parse(JSON.stringify(testData.responseHelper)) - ); - - var cityValues = data.getFacetValues('city'); - var expectedCityValues = [ - { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, - { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, - { - name: 'San Francisco', - escapedValue: 'San Francisco', - count: 1, - isRefined: false, - }, - ]; - - expect(cityValues).toEqual(expectedCityValues); - - var cityValuesCustom = data.getFacetValues('city', { - sortBy: ['count:asc', 'name:asc'], +test('searchOnce should call the algolia client according to the number of refinements and call callback with no error and with results when no error', function () { + return new Promise(function (done) { + var testData = require('../../datasets/SearchParameters/search.dataset')(); + + var client = { + search: vi.fn().mockImplementationOnce(function () { + return Promise.resolve(testData.response); + }), + }; + + var helper = algoliasearchHelper(client, 'test_hotels-node'); + + var parameters = new SearchParameters({ + disjunctiveFacets: ['city'], + }) + .setIndex('test_hotels-node') + .addDisjunctiveFacetRefinement('city', 'Paris') + .addDisjunctiveFacetRefinement('city', 'New York'); + + helper.searchOnce(parameters, function (err, data) { + expect(err).toBe(null); + + // shame deepclone, to remove any associated methods coming from the results + expect(JSON.parse(JSON.stringify(data))).toEqual( + JSON.parse(JSON.stringify(testData.responseHelper)) + ); + + var cityValues = data.getFacetValues('city'); + var expectedCityValues = [ + { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, + { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, + { + name: 'San Francisco', + escapedValue: 'San Francisco', + count: 1, + isRefined: false, + }, + ]; + + expect(cityValues).toEqual(expectedCityValues); + + var cityValuesCustom = data.getFacetValues('city', { + sortBy: ['count:asc', 'name:asc'], + }); + var expectedCityValuesCustom = [ + { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, + { + name: 'San Francisco', + escapedValue: 'San Francisco', + count: 1, + isRefined: false, + }, + { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, + ]; + + expect(cityValuesCustom).toEqual(expectedCityValuesCustom); + + var cityValuesFn = data.getFacetValues('city', { + sortBy: function (a, b) { + return a.count - b.count; + }, + }); + var expectedCityValuesFn = [ + { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, + { + name: 'San Francisco', + escapedValue: 'San Francisco', + count: 1, + isRefined: false, + }, + { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, + ]; + + expect(cityValuesFn).toEqual(expectedCityValuesFn); + + expect(client.search).toHaveBeenCalledTimes(1); + + var queries = client.search.mock.calls[0][0]; + for (var i = 0; i < queries.length; i++) { + var query = queries[i]; + expect(query.query).toBeUndefined(); + expect(query.params.query).toBeUndefined(); + } + + done(); }); - var expectedCityValuesCustom = [ - { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, - { - name: 'San Francisco', - escapedValue: 'San Francisco', - count: 1, - isRefined: false, - }, - { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, - ]; - - expect(cityValuesCustom).toEqual(expectedCityValuesCustom); - - var cityValuesFn = data.getFacetValues('city', { - sortBy: function (a, b) { - return a.count - b.count; - }, - }); - var expectedCityValuesFn = [ - { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, - { - name: 'San Francisco', - escapedValue: 'San Francisco', - count: 1, - isRefined: false, - }, - { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, - ]; - - expect(cityValuesFn).toEqual(expectedCityValuesFn); - - expect(client.search).toHaveBeenCalledTimes(1); - - var queries = client.search.mock.calls[0][0]; - for (var i = 0; i < queries.length; i++) { - var query = queries[i]; - expect(query.query).toBeUndefined(); - expect(query.params.query).toBeUndefined(); - } - - done(); }); }); -test('searchOnce should call the algolia client according to the number of refinements and call callback with error and no results when error', function (done) { - var error = { message: 'error' }; - var client = { - search: jest.fn().mockImplementationOnce(function () { - return Promise.reject(error); - }), - }; - - var helper = algoliasearchHelper(client, 'test_hotels-node'); - - var parameters = new SearchParameters({ - disjunctiveFacets: ['city'], - }) - .setIndex('test_hotels-node') - .addDisjunctiveFacetRefinement('city', 'Paris') - .addDisjunctiveFacetRefinement('city', 'New York'); - - helper.searchOnce(parameters, function (err, data) { - expect(err).toBe(error); - expect(data).toBe(null); - - expect(client.search).toHaveBeenCalledTimes(1); - - var queries = client.search.mock.calls[0][0]; - for (var i = 0; i < queries.length; i++) { - var query = queries[i]; - expect(query.query).toBeUndefined(); - expect(query.params.query).toBeUndefined(); - } - - done(); +test('searchOnce should call the algolia client according to the number of refinements and call callback with error and no results when error', function () { + return new Promise(function (done) { + var error = { message: 'error' }; + var client = { + search: vi.fn().mockImplementationOnce(function () { + return Promise.reject(error); + }), + }; + + var helper = algoliasearchHelper(client, 'test_hotels-node'); + + var parameters = new SearchParameters({ + disjunctiveFacets: ['city'], + }) + .setIndex('test_hotels-node') + .addDisjunctiveFacetRefinement('city', 'Paris') + .addDisjunctiveFacetRefinement('city', 'New York'); + + helper.searchOnce(parameters, function (err, data) { + expect(err).toBe(error); + expect(data).toBe(null); + + expect(client.search).toHaveBeenCalledTimes(1); + + var queries = client.search.mock.calls[0][0]; + for (var i = 0; i < queries.length; i++) { + var query = queries[i]; + expect(query.query).toBeUndefined(); + expect(query.params.query).toBeUndefined(); + } + + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/setQueryParameter.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/setQueryParameter.js index 699b98d01ae..69b6efdd1fb 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/setQueryParameter.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/setQueryParameter.js @@ -39,7 +39,7 @@ test('setChange should not change the current state: no real modification', func test('setQueryParameter should warn about invalid userToken', function () { const message = '[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}'; - console.warn = jest.fn(); + console.warn = vi.fn(); var helper = algoliasearchHelper(fakeClient, null, {}); helper.setQueryParameter('userToken', null); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/state.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/state.js index 9e408b9d3b2..33aa5d50434 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/state.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/state.js @@ -6,21 +6,23 @@ var SearchParameters = algoliasearchHelper.SearchParameters; var fakeClient = {}; -test('setState should set the state of the helper and trigger a change event', function (done) { - var state0 = { query: 'a query' }; - var state1 = { query: 'another query' }; +test('setState should set the state of the helper and trigger a change event', function () { + return new Promise(function (done) { + var state0 = { query: 'a query' }; + var state1 = { query: 'another query' }; - var helper = algoliasearchHelper(fakeClient, null, state0); + var helper = algoliasearchHelper(fakeClient, null, state0); - expect(helper.state).toEqual(new SearchParameters(state0)); + expect(helper.state).toEqual(new SearchParameters(state0)); - helper.on('change', function (event) { - expect(helper.state).toEqual(new SearchParameters(state1)); - expect(event.state).toEqual(new SearchParameters(state1)); - done(); - }); + helper.on('change', function (event) { + expect(helper.state).toEqual(new SearchParameters(state1)); + expect(event.state).toEqual(new SearchParameters(state1)); + done(); + }); - helper.setState(state1); + helper.setState(state1); + }); }); test('setState should set a default hierarchicalFacetRefinement when a rootPath is defined', function () { @@ -66,7 +68,7 @@ test('setState should set a default hierarchicalFacetRefinement when a rootPath test('setState should warn about invalid userToken', function () { const message = '[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}'; - console.warn = jest.fn(); + console.warn = vi.fn(); var helper = algoliasearchHelper(fakeClient, null, {}); helper.setState({ userToken: null }); diff --git a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/tags.js b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/tags.js index d7d0dc9d9d1..7556e7fcbf4 100644 --- a/packages/algoliasearch-helper/test/spec/algoliasearch.helper/tags.js +++ b/packages/algoliasearch-helper/test/spec/algoliasearch.helper/tags.js @@ -26,40 +26,42 @@ test('Tags filters: advanced query', function () { expect(requestBuilder._getTagFilters(helper.state)).toEqual(complexQuery); }); -test('Tags filters: switching between advanced and simple API should be forbidden without clearing the refinements first', function (done) { - var helper = algoliasearchHelper(fakeClient, null, null); +test('Tags filters: switching between advanced and simple API should be forbidden without clearing the refinements first', function () { + return new Promise(function (done) { + var helper = algoliasearchHelper(fakeClient, null, null); - helper.addTag('tag').addTag('tag2'); - expect(requestBuilder._getTagFilters(helper.state)).toEqual('tag,tag2'); + helper.addTag('tag').addTag('tag2'); + expect(requestBuilder._getTagFilters(helper.state)).toEqual('tag,tag2'); - var complexQuery = '(sea, city), romantic, -mountain'; + var complexQuery = '(sea, city), romantic, -mountain'; - try { - helper.setQueryParameter('tagFilters', complexQuery); - done( - new Error( - "Can't switch directly from the advanced API to the managed API" - ) - ); - } catch (e0) { - helper.clearTags().setQueryParameter('tagFilters', complexQuery); - expect(requestBuilder._getTagFilters(helper.state)).toEqual(complexQuery); - } + try { + helper.setQueryParameter('tagFilters', complexQuery); + done( + new Error( + "Can't switch directly from the advanced API to the managed API" + ) + ); + } catch (e0) { + helper.clearTags().setQueryParameter('tagFilters', complexQuery); + expect(requestBuilder._getTagFilters(helper.state)).toEqual(complexQuery); + } - try { - helper.addTag('tag').addTag('tag2'); - done( - new Error( - "Can't switch directly from the managed API to the advanced API" - ) - ); - } catch (e1) { - helper - .setQueryParameter('tagFilters', undefined) - .addTag('tag') - .addTag('tag2'); - expect(requestBuilder._getTagFilters(helper.state)).toEqual('tag,tag2'); - } + try { + helper.addTag('tag').addTag('tag2'); + done( + new Error( + "Can't switch directly from the managed API to the advanced API" + ) + ); + } catch (e1) { + helper + .setQueryParameter('tagFilters', undefined) + .addTag('tag') + .addTag('tag2'); + expect(requestBuilder._getTagFilters(helper.state)).toEqual('tag,tag2'); + } - done(); + done(); + }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/attributes-order.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/attributes-order.js index 37f0c85a4df..7714d0fcd77 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/attributes-order.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/attributes-order.js @@ -2,131 +2,133 @@ // different order than the declared attributes order at the helper initialization 'use strict'; -test('hierarchical facets: attributes order', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: attributes order', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-toggleRefine-appId'; - var apiKey = 'hierarchical-toggleRefine-apiKey'; - var indexName = 'hierarchical-toggleRefine-indexName'; + var appId = 'hierarchical-toggleRefine-appId'; + var apiKey = 'hierarchical-toggleRefine-apiKey'; + var indexName = 'hierarchical-toggleRefine-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0', 'categories.lvl1'], - }, - ], - }); - - helper.toggleFacetRefinement('categories', 'beers'); - - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 3, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - // /!\ Note that lvl1 comes *before* lvl0 here - 'categories.lvl1': { 'beers > IPA': 6, 'beers > 1664': 3 }, - 'categories.lvl0': { beers: 9 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 9, fruits: 5, sales: 20 }, - }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 9, - isRefined: true, - exhaustive: true, - data: [ - { - name: '1664', - path: 'beers > 1664', - escapedValue: 'beers > 1664', - count: 3, - isRefined: false, - exhaustive: true, - data: null, - }, - { - name: 'IPA', - path: 'beers > IPA', - escapedValue: 'beers > IPA', - count: 6, - isRefined: false, - exhaustive: true, - data: null, - }, - ], + name: 'categories', + attributes: ['categories.lvl0', 'categories.lvl1'], }, + ], + }); + + helper.toggleFacetRefinement('categories', 'beers'); + + var algoliaResponse = { + results: [ { - name: 'fruits', - path: 'fruits', - escapedValue: 'fruits', - count: 5, - isRefined: false, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 3, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + // /!\ Note that lvl1 comes *before* lvl0 here + 'categories.lvl1': { 'beers > IPA': 6, 'beers > 1664': 3 }, + 'categories.lvl0': { beers: 9 }, + }, }, { - name: 'sales', - path: 'sales', - escapedValue: 'sales', - count: 20, - isRefined: false, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 9, fruits: 5, sales: 20 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 9, + isRefined: true, + exhaustive: true, + data: [ + { + name: '1664', + path: 'beers > 1664', + escapedValue: 'beers > 1664', + count: 3, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'IPA', + path: 'beers > IPA', + escapedValue: 'beers > IPA', + count: 6, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + { + name: 'fruits', + path: 'fruits', + escapedValue: 'fruits', + count: 5, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'sales', + path: 'sales', + escapedValue: 'sales', + count: 20, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); + helper.setQuery('a').search(); - helper.once('result', function (event) { - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - expect(event.results.getFacetByName('categories')).toEqual( - expectedHelperResponse[0] - ); + helper.once('result', function (event) { + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + expect(event.results.getFacetByName('categories')).toEqual( + expectedHelperResponse[0] + ); - done(); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/custom-prefix-path.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/custom-prefix-path.js index 5da483e52a2..20fdeb94286 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/custom-prefix-path.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/custom-prefix-path.js @@ -1,135 +1,137 @@ 'use strict'; -test('hierarchical facets: custom prefix path', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: custom prefix path', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0', 'categories.lvl1', 'categories.lvl2'], - rootPath: 'beers', - separator: ' | ', - }, - ], - }); + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: ['categories.lvl0', 'categories.lvl1', 'categories.lvl2'], + rootPath: 'beers', + separator: ' | ', + }, + ], + }); - helper.toggleRefine('categories', 'beers | Belgian'); + helper.toggleRefine('categories', 'beers | Belgian'); - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }, { objectID: 'two' }], - nbHits: 2, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { beers: 3 }, - 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, - 'categories.lvl2': { - 'beers | Belgian | Blond': 2, - 'beers | Belgian | Dark': 1, + var algoliaResponse = { + results: [ + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }, { objectID: 'two' }], + nbHits: 2, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { beers: 3 }, + 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, + 'categories.lvl2': { + 'beers | Belgian | Blond': 2, + 'beers | Belgian | Dark': 1, + }, }, }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 3 }, - 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, - }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ { - name: 'Belgian', - path: 'beers | Belgian', - escapedValue: 'beers | Belgian', - count: 1, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'Blond', - path: 'beers | Belgian | Blond', - escapedValue: 'beers | Belgian | Blond', - count: 2, - isRefined: false, - exhaustive: true, - data: null, - }, - { - name: 'Dark', - path: 'beers | Belgian | Dark', - escapedValue: 'beers | Belgian | Dark', - count: 1, - isRefined: false, - exhaustive: true, - data: null, - }, - ], + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 3 }, + 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, + }, }, { - name: 'IPA', - path: 'beers | IPA', - escapedValue: 'beers | IPA', - count: 2, - isRefined: false, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'Belgian', + path: 'beers | Belgian', + escapedValue: 'beers | Belgian', + count: 1, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'Blond', + path: 'beers | Belgian | Blond', + escapedValue: 'beers | Belgian | Blond', + count: 2, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'Dark', + path: 'beers | Belgian | Dark', + escapedValue: 'beers | Belgian | Dark', + count: 1, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + { + name: 'IPA', + path: 'beers | IPA', + escapedValue: 'beers | IPA', + count: 2, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - expect(client.search).toHaveBeenCalledTimes(1); - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + helper.setQuery('a').search(); + helper.once('result', function (event) { + expect(client.search).toHaveBeenCalledTimes(1); + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/custom-separator.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/custom-separator.js index d1328e0a6c2..62fc8e8d130 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/custom-separator.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/custom-separator.js @@ -1,139 +1,141 @@ 'use strict'; -test('hierarchical facets: custom separator', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: custom separator', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0', 'categories.lvl1'], - separator: ' | ', - }, - ], - }); + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: ['categories.lvl0', 'categories.lvl1'], + separator: ' | ', + }, + ], + }); - helper.toggleRefine('categories', 'beers | IPA'); + helper.toggleRefine('categories', 'beers | IPA'); - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }, { objectID: 'two' }], - nbHits: 2, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { beers: 2 }, - 'categories.lvl1': { 'beers | IPA': 2 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 3 }, - 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, + var algoliaResponse = { + results: [ + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }, { objectID: 'two' }], + nbHits: 2, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { beers: 2 }, + 'categories.lvl1': { 'beers | IPA': 2 }, + }, }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 3 }, + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 3 }, + 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, + }, }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 3, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'IPA', - path: 'beers | IPA', - escapedValue: 'beers | IPA', - count: 2, - isRefined: true, - exhaustive: true, - data: null, - }, - { - name: 'Belgian', - path: 'beers | Belgian', - escapedValue: 'beers | Belgian', - count: 1, - isRefined: false, - exhaustive: true, - data: null, - }, - ], + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 3 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 3, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'IPA', + path: 'beers | IPA', + escapedValue: 'beers | IPA', + count: 2, + isRefined: true, + exhaustive: true, + data: null, + }, + { + name: 'Belgian', + path: 'beers | Belgian', + escapedValue: 'beers | Belgian', + count: 1, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - var queries = client.search.mock.calls[0][0]; - var hitsQuery = queries[0]; - var parentValuesQuery = queries[1]; + helper.setQuery('a').search(); + helper.once('result', function (event) { + var queries = client.search.mock.calls[0][0]; + var hitsQuery = queries[0]; + var parentValuesQuery = queries[1]; - expect(client.search).toHaveBeenCalledTimes(1); - expect(hitsQuery.params.facets).toEqual([ - 'categories.lvl0', - 'categories.lvl1', - ]); - expect(hitsQuery.params.facetFilters).toEqual([ - ['categories.lvl1:beers | IPA'], - ]); - expect(parentValuesQuery.params.facets).toEqual([ - 'categories.lvl0', - 'categories.lvl1', - ]); - expect(parentValuesQuery.params.facetFilters).toEqual([ - ['categories.lvl0:beers'], - ]); - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + expect(client.search).toHaveBeenCalledTimes(1); + expect(hitsQuery.params.facets).toEqual([ + 'categories.lvl0', + 'categories.lvl1', + ]); + expect(hitsQuery.params.facetFilters).toEqual([ + ['categories.lvl1:beers | IPA'], + ]); + expect(parentValuesQuery.params.facets).toEqual([ + 'categories.lvl0', + 'categories.lvl1', + ]); + expect(parentValuesQuery.params.facetFilters).toEqual([ + ['categories.lvl0:beers'], + ]); + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/do-not-show-parent-level.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/do-not-show-parent-level.js index dcde21476e9..2fcaf853024 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/do-not-show-parent-level.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/do-not-show-parent-level.js @@ -1,113 +1,115 @@ 'use strict'; -test('hierarchical facets: do not show parent level', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: do not show parent level', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0', 'categories.lvl1'], - separator: ' | ', - showParentLevel: false, - }, - ], - }); + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: ['categories.lvl0', 'categories.lvl1'], + separator: ' | ', + showParentLevel: false, + }, + ], + }); - helper.toggleRefine('categories', 'beers | IPA'); + helper.toggleRefine('categories', 'beers | IPA'); - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }, { objectID: 'two' }], - nbHits: 2, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { beers: 2 }, - 'categories.lvl1': { 'beers | IPA': 2 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 3 }, - 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, + var algoliaResponse = { + results: [ + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }, { objectID: 'two' }], + nbHits: 2, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { beers: 2 }, + 'categories.lvl1': { 'beers | IPA': 2 }, + }, }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 3 }, + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 3 }, + 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, + }, }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 3, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'IPA', - path: 'beers | IPA', - escapedValue: 'beers | IPA', - count: 2, - isRefined: true, - exhaustive: true, - data: null, - }, - ], + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 3 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 3, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'IPA', + path: 'beers | IPA', + escapedValue: 'beers | IPA', + count: 2, + isRefined: true, + exhaustive: true, + data: null, + }, + ], + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - expect(client.search).toHaveBeenCalledTimes(1); - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + helper.setQuery('a').search(); + helper.once('result', function (event) { + expect(client.search).toHaveBeenCalledTimes(1); + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/facet-value-length.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/facet-value-length.js index 7799b9ac7e1..e86fd06877a 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/facet-value-length.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/facet-value-length.js @@ -1,81 +1,83 @@ 'use strict'; -test('hierarchical facets: facet value called length', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); +test('hierarchical facets: facet value called length', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0'], - }, - ], - }); - - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 3, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - // value length can cause lodash to turn an object into an array - 'categories.lvl0': { beers: 8, length: 3 }, - }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 8, - isRefined: false, - exhaustive: true, - data: null, + name: 'categories', + attributes: ['categories.lvl0'], }, + ], + }); + + var algoliaResponse = { + results: [ { - name: 'length', - path: 'length', - escapedValue: 'length', - count: 3, - isRefined: false, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 3, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + // value length can cause lodash to turn an object into an array + 'categories.lvl0': { beers: 8, length: 3 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 8, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'length', + path: 'length', + escapedValue: 'length', + count: 3, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.search(); - helper.once('result', function (event) { - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + helper.search(); + helper.once('result', function (event) { + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/no-refinement.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/no-refinement.js index 0ff631ed54b..ddbebaa2aa6 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/no-refinement.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/no-refinement.js @@ -1,88 +1,90 @@ 'use strict'; -test('hierarchical facets: no refinement', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: no refinement', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0'], - }, - ], - }); - - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }, { objectID: 'two' }], - nbHits: 5, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { beers: 2, fruits: 3 }, - }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 2, - isRefined: false, - exhaustive: true, - data: null, + name: 'categories', + attributes: ['categories.lvl0'], }, + ], + }); + + var algoliaResponse = { + results: [ { - name: 'fruits', - path: 'fruits', - escapedValue: 'fruits', - count: 3, - isRefined: false, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }, { objectID: 'two' }], + nbHits: 5, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { beers: 2, fruits: 3 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 2, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'fruits', + path: 'fruits', + escapedValue: 'fruits', + count: 3, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - var queries = client.search.mock.calls[0][0]; - var hitsQuery = queries[0]; + helper.setQuery('a').search(); + helper.once('result', function (event) { + var queries = client.search.mock.calls[0][0]; + var hitsQuery = queries[0]; - expect(queries.length).toBe(1); - expect(client.search).toHaveBeenCalledTimes(1); - expect(hitsQuery.params.facets).toEqual(['categories.lvl0']); - expect(hitsQuery.params.facetFilters).toBe(undefined); - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + expect(queries.length).toBe(1); + expect(client.search).toHaveBeenCalledTimes(1); + expect(hitsQuery.params.facets).toEqual(['categories.lvl0']); + expect(hitsQuery.params.facetFilters).toBe(undefined); + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/no-trim.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/no-trim.js index deeda589328..abfddff99e9 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/no-trim.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/no-trim.js @@ -1,132 +1,134 @@ 'use strict'; -test('hierarchical facets: do not trim facetFilters values', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: do not trim facetFilters values', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0', 'categories.lvl1'], - separator: '>', - }, - ], - }); + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: ['categories.lvl0', 'categories.lvl1'], + separator: '>', + }, + ], + }); - helper.toggleRefine('categories', ' beers > IPA '); - helper.toggleRefine('categories', ' beers > IPA '); - helper.toggleRefine('categories', ' beers > IPA '); + helper.toggleRefine('categories', ' beers > IPA '); + helper.toggleRefine('categories', ' beers > IPA '); + helper.toggleRefine('categories', ' beers > IPA '); - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }, { objectID: 'two' }], - nbHits: 2, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { ' beers ': 2 }, - 'categories.lvl1': { ' beers > IPA ': 2 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { ' beers ': 3 }, - 'categories.lvl1': { ' beers > IPA ': 2, ' beers > Belgian': 1 }, + var algoliaResponse = { + results: [ + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }, { objectID: 'two' }], + nbHits: 2, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { ' beers ': 2 }, + 'categories.lvl1': { ' beers > IPA ': 2 }, + }, }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { ' beers ': 3 }, + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { ' beers ': 3 }, + 'categories.lvl1': { ' beers > IPA ': 2, ' beers > Belgian': 1 }, + }, }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ { - name: 'beers', - path: ' beers ', - escapedValue: ' beers ', - count: 3, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'IPA', - path: ' beers > IPA ', - escapedValue: ' beers > IPA ', - count: 2, - isRefined: true, - exhaustive: true, - data: null, - }, - { - name: 'Belgian', - path: ' beers > Belgian', - escapedValue: ' beers > Belgian', - count: 1, - isRefined: false, - exhaustive: true, - data: null, - }, - ], + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { ' beers ': 3 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: ' beers ', + escapedValue: ' beers ', + count: 3, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'IPA', + path: ' beers > IPA ', + escapedValue: ' beers > IPA ', + count: 2, + isRefined: true, + exhaustive: true, + data: null, + }, + { + name: 'Belgian', + path: ' beers > Belgian', + escapedValue: ' beers > Belgian', + count: 1, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - var queries = client.search.mock.calls[0][0]; - var hitsQuery = queries[0]; - var parentValuesQuery = queries[1]; + helper.setQuery('a').search(); + helper.once('result', function (event) { + var queries = client.search.mock.calls[0][0]; + var hitsQuery = queries[0]; + var parentValuesQuery = queries[1]; - expect(hitsQuery.params.facetFilters).toEqual([ - ['categories.lvl1: beers > IPA '], - ]); - expect(parentValuesQuery.params.facetFilters).toEqual([ - ['categories.lvl0: beers '], - ]); - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + expect(hitsQuery.params.facetFilters).toEqual([ + ['categories.lvl1: beers > IPA '], + ]); + expect(parentValuesQuery.params.facetFilters).toEqual([ + ['categories.lvl0: beers '], + ]); + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/objects-with-multiple-categories.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/objects-with-multiple-categories.js index e65f1077563..0195e83c8dc 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/objects-with-multiple-categories.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/objects-with-multiple-categories.js @@ -1,132 +1,134 @@ 'use strict'; -test('hierarchical facets: objects with multiple categories', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: objects with multiple categories', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0', 'categories.lvl1'], - }, - ], - }); + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: ['categories.lvl0', 'categories.lvl1'], + }, + ], + }); - helper.toggleRefine('categories', 'beers > IPA'); + helper.toggleRefine('categories', 'beers > IPA'); - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 3, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { beers: 3, bières: 3 }, - 'categories.lvl1': { 'beers > IPA': 3, 'bières > Rousses': 3 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 20, - facets: { - 'categories.lvl0': { beers: 5, bières: 3 }, - 'categories.lvl1': { - 'beers > IPA': 3, - 'beers > Guiness': 2, - 'bières > Rousses': 3, + var algoliaResponse = { + results: [ + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 3, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { beers: 3, bières: 3 }, + 'categories.lvl1': { 'beers > IPA': 3, 'bières > Rousses': 3 }, }, }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 20, - facets: { - 'categories.lvl0': { beers: 5, bières: 3 }, - }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 5, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'IPA', - path: 'beers > IPA', - escapedValue: 'beers > IPA', - count: 3, - isRefined: true, - exhaustive: true, - data: null, - }, - { - name: 'Guiness', - path: 'beers > Guiness', - escapedValue: 'beers > Guiness', - count: 2, - isRefined: false, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 20, + facets: { + 'categories.lvl0': { beers: 5, bières: 3 }, + 'categories.lvl1': { + 'beers > IPA': 3, + 'beers > Guiness': 2, + 'bières > Rousses': 3, }, - ], + }, }, { - name: 'bières', - path: 'bières', - escapedValue: 'bières', - count: 3, - isRefined: false, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 20, + facets: { + 'categories.lvl0': { beers: 5, bières: 3 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 5, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'IPA', + path: 'beers > IPA', + escapedValue: 'beers > IPA', + count: 3, + isRefined: true, + exhaustive: true, + data: null, + }, + { + name: 'Guiness', + path: 'beers > Guiness', + escapedValue: 'beers > Guiness', + count: 2, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + { + name: 'bières', + path: 'bières', + escapedValue: 'bières', + count: 3, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + helper.setQuery('a').search(); + helper.once('result', function (event) { + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/one-level.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/one-level.js index 38557be4537..7839ddd6108 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/one-level.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/one-level.js @@ -1,105 +1,107 @@ 'use strict'; -test('hierarchical facets: only one level deep', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: only one level deep', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0'], - }, - ], - }); - - helper.toggleRefine('categories', 'beers'); - - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }, { objectID: 'two' }], - nbHits: 2, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { beers: 2 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 2, fruits: 3 }, + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: ['categories.lvl0'], }, - }, - ], - }; + ], + }); - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ + helper.toggleRefine('categories', 'beers'); + + var algoliaResponse = { + results: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 2, - isRefined: true, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }, { objectID: 'two' }], + nbHits: 2, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { beers: 2 }, + }, }, { - name: 'fruits', - path: 'fruits', - escapedValue: 'fruits', - count: 3, - isRefined: false, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 2, fruits: 3 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 2, + isRefined: true, + exhaustive: true, + data: null, + }, + { + name: 'fruits', + path: 'fruits', + escapedValue: 'fruits', + count: 3, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - var queries = client.search.mock.calls[0][0]; - var hitsQuery = queries[0]; - var parentValuesQuery = queries[1]; + helper.setQuery('a').search(); + helper.once('result', function (event) { + var queries = client.search.mock.calls[0][0]; + var hitsQuery = queries[0]; + var parentValuesQuery = queries[1]; - expect(queries.length).toBe(2); - expect(client.search).toHaveBeenCalledTimes(1); - expect(hitsQuery.params.facets).toEqual(['categories.lvl0']); - expect(hitsQuery.params.facetFilters).toEqual([['categories.lvl0:beers']]); - expect(parentValuesQuery.params.facets).toEqual(['categories.lvl0']); - expect(parentValuesQuery.params.facetFilters).toBe(undefined); - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + expect(queries.length).toBe(2); + expect(client.search).toHaveBeenCalledTimes(1); + expect(hitsQuery.params.facets).toEqual(['categories.lvl0']); + expect(hitsQuery.params.facetFilters).toEqual([['categories.lvl0:beers']]); + expect(parentValuesQuery.params.facets).toEqual(['categories.lvl0']); + expect(parentValuesQuery.params.facetFilters).toBe(undefined); + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/pagination.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/pagination.js index 724cecfbd2e..51e22173255 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/pagination.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/pagination.js @@ -1,106 +1,108 @@ 'use strict'; -test('hierarchical facets: pagination', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: pagination', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-toggleRefine-appId'; - var apiKey = 'hierarchical-toggleRefine-apiKey'; - var indexName = 'hierarchical-toggleRefine-indexName'; + var appId = 'hierarchical-toggleRefine-appId'; + var apiKey = 'hierarchical-toggleRefine-apiKey'; + var indexName = 'hierarchical-toggleRefine-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: [ - 'categories.lvl0', - 'categories.lvl1', - 'categories.lvl2', - 'categories.lvl3', - ], - }, - ], - }); + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: [ + 'categories.lvl0', + 'categories.lvl1', + 'categories.lvl2', + 'categories.lvl3', + ], + }, + ], + }); - helper.toggleRefine('categories', 'beers > IPA > Flying dog'); + helper.toggleRefine('categories', 'beers > IPA > Flying dog'); - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 3, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { beers: 3, sales: 3 }, - 'categories.lvl1': { 'beers > IPA': 3, 'sales > IPA': 3 }, - 'categories.lvl2': { - 'beers > IPA > Flying dog': 3, - 'sales > IPA > Flying dog': 3, + var algoliaResponse = { + results: [ + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 3, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { beers: 3, sales: 3 }, + 'categories.lvl1': { 'beers > IPA': 3, 'sales > IPA': 3 }, + 'categories.lvl2': { + 'beers > IPA > Flying dog': 3, + 'sales > IPA > Flying dog': 3, + }, }, }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 9 }, - 'categories.lvl1': { 'beers > IPA': 9 }, - 'categories.lvl2': { - 'beers > IPA > Flying dog': 3, - 'sales > IPA > Flying dog': 3, - 'beers > IPA > Brewdog punk IPA': 6, + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 9 }, + 'categories.lvl1': { 'beers > IPA': 9 }, + 'categories.lvl2': { + 'beers > IPA > Flying dog': 3, + 'sales > IPA > Flying dog': 3, + 'beers > IPA > Brewdog punk IPA': 6, + }, }, }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 20, fruits: 5, sales: 20 }, + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 20, fruits: 5, sales: 20 }, + }, }, - }, - ], - }; + ], + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery(''); - helper.setCurrentPage(1); - helper.toggleRefine('categories', 'beers > IPA > Flying dog'); - helper.search(); + helper.setQuery(''); + helper.setCurrentPage(1); + helper.toggleRefine('categories', 'beers > IPA > Flying dog'); + helper.search(); - helper.once('result', function () { - var queries = client.search.mock.calls[0][0]; - var hitsQuery = queries[0]; + helper.once('result', function () { + var queries = client.search.mock.calls[0][0]; + var hitsQuery = queries[0]; - expect(hitsQuery.params.page).toBe(0); + expect(hitsQuery.params.page).toBe(0); - // we do not yet support multiple values for hierarchicalFacetsRefinements - // but at some point we may want to open multiple leafs of a hierarchical menu - // So we set this as an array so that we do not have to bump major to handle it - expect( - Array.isArray(helper.state.hierarchicalFacetsRefinements.categories) - ).toBeTruthy(); - done(); + // we do not yet support multiple values for hierarchicalFacetsRefinements + // but at some point we may want to open multiple leafs of a hierarchical menu + // So we set this as an array so that we do not have to bump major to handle it + expect( + Array.isArray(helper.state.hierarchicalFacetsRefinements.categories) + ).toBeTruthy(); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/parent-toggleRefine.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/parent-toggleRefine.js index ccdfc1c890b..ae891b8829c 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/parent-toggleRefine.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/parent-toggleRefine.js @@ -25,7 +25,7 @@ test('hierarchical facets: toggleRefine behavior', function () { ], }); - client.search = jest.fn(function () { + client.search = vi.fn(function () { return new Promise(function () {}); }); @@ -76,7 +76,7 @@ test('hierarchical facets: toggleRefine behavior when root level', function () { ], }); - client.search = jest.fn(function () { + client.search = vi.fn(function () { return new Promise(function () {}); }); @@ -118,7 +118,7 @@ test('hierarchical facets: toggleRefine behavior when different root level', fun ], }); - client.search = jest.fn(function () { + client.search = vi.fn(function () { return new Promise(function () {}); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/refined-no-result.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/refined-no-result.js index 9147ee1d471..1a1f3b2f548 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/refined-no-result.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/refined-no-result.js @@ -1,90 +1,92 @@ 'use strict'; -test('hierarchical facets: no results', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: no results', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-toggleRefine-appId'; - var apiKey = 'hierarchical-toggleRefine-apiKey'; - var indexName = 'hierarchical-toggleRefine-indexName'; + var appId = 'hierarchical-toggleRefine-appId'; + var apiKey = 'hierarchical-toggleRefine-apiKey'; + var indexName = 'hierarchical-toggleRefine-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: [ - 'categories.lvl0', - 'categories.lvl1', - 'categories.lvl2', - 'categories.lvl3', - ], - }, - ], - }); + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: [ + 'categories.lvl0', + 'categories.lvl1', + 'categories.lvl2', + 'categories.lvl3', + ], + }, + ], + }); - helper.toggleRefine('categories', 'beers > IPA > Flying dog'); + helper.toggleRefine('categories', 'beers > IPA > Flying dog'); - var algoliaResponse = { - results: [ - { - query: 'badquery', - index: indexName, - hits: [], - nbHits: 0, - page: 0, - nbPages: 0, - hitsPerPage: 6, - exhaustiveFacetsCount: true, - facets: {}, - }, - { - query: 'badquery', - index: indexName, - hits: [], - nbHits: 0, - page: 0, - nbPages: 0, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 20, fruits: 5, sales: 20 }, + var algoliaResponse = { + results: [ + { + query: 'badquery', + index: indexName, + hits: [], + nbHits: 0, + page: 0, + nbPages: 0, + hitsPerPage: 6, + exhaustiveFacetsCount: true, + facets: {}, + }, + { + query: 'badquery', + index: indexName, + hits: [], + nbHits: 0, + page: 0, + nbPages: 0, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 20, fruits: 5, sales: 20 }, + }, }, - }, - { - query: 'badquery', - index: indexName, - hits: [], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 20, fruits: 5, sales: 20 }, + { + query: 'badquery', + index: indexName, + hits: [], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 20, fruits: 5, sales: 20 }, + }, }, - }, - ], - }; + ], + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('badquery').search(); + helper.setQuery('badquery').search(); - helper.once('result', function (event) { - expect(event.results.hierarchicalFacets).toEqual([ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: null, - }, - ]); - done(); + helper.once('result', function (event) { + expect(event.results.hierarchicalFacets).toEqual([ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: null, + }, + ]); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/show-parent-level.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/show-parent-level.js index 6723174451a..1bed6d123c8 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/show-parent-level.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/show-parent-level.js @@ -1,122 +1,124 @@ 'use strict'; -test('hierarchical facets: show parent level', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: show parent level', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: ['categories.lvl0', 'categories.lvl1'], - separator: ' | ', - showParentLevel: true, - }, - ], - }); + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: ['categories.lvl0', 'categories.lvl1'], + separator: ' | ', + showParentLevel: true, + }, + ], + }); - helper.toggleRefine('categories', 'beers | IPA'); + helper.toggleRefine('categories', 'beers | IPA'); - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }, { objectID: 'two' }], - nbHits: 2, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { beers: 2 }, - 'categories.lvl1': { 'beers | IPA': 2 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 3 }, - 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, + var algoliaResponse = { + results: [ + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }, { objectID: 'two' }], + nbHits: 2, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { beers: 2 }, + 'categories.lvl1': { 'beers | IPA': 2 }, + }, }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 3 }, + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 3 }, + 'categories.lvl1': { 'beers | IPA': 2, 'beers | Belgian': 1 }, + }, }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 3, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'IPA', - path: 'beers | IPA', - escapedValue: 'beers | IPA', - count: 2, - isRefined: true, - exhaustive: true, - data: null, - }, - { - name: 'Belgian', - path: 'beers | Belgian', - escapedValue: 'beers | Belgian', - count: 1, - isRefined: false, - exhaustive: true, - data: null, - }, - ], + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 3 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 3, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'IPA', + path: 'beers | IPA', + escapedValue: 'beers | IPA', + count: 2, + isRefined: true, + exhaustive: true, + data: null, + }, + { + name: 'Belgian', + path: 'beers | Belgian', + escapedValue: 'beers | Belgian', + count: 1, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - expect(client.search).toHaveBeenCalledTimes(1); - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + helper.setQuery('a').search(); + helper.once('result', function (event) { + expect(client.search).toHaveBeenCalledTimes(1); + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/simple-usage.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/simple-usage.js index 5261f747911..9675dde0e7a 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/simple-usage.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/simple-usage.js @@ -78,7 +78,7 @@ describe('hierarchical facets: simple usage', function () { }; var client = algoliasearch(appId, apiKey); - client.search = jest.fn(function () { + client.search = vi.fn(function () { return Promise.resolve(algoliaResponse); }); @@ -86,334 +86,338 @@ describe('hierarchical facets: simple usage', function () { client.search.mockClear(); }); - test('persistHierarchicalRootCount: false', function (done) { - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: [ - 'categories.lvl0', - 'categories.lvl1', - 'categories.lvl2', - 'categories.lvl3', - ], - }, - ], - }); - - helper.toggleRefine('categories', 'beers > IPA > Flying dog'); - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ + test('persistHierarchicalRootCount: false', function () { + return new Promise(function (done) { + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 9, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'IPA', - path: 'beers > IPA', - escapedValue: 'beers > IPA', - count: 9, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'Flying dog', - path: 'beers > IPA > Flying dog', - escapedValue: 'beers > IPA > Flying dog', - count: 3, - isRefined: true, - exhaustive: true, - data: null, - }, - { - name: 'Brewdog punk IPA', - path: 'beers > IPA > Brewdog punk IPA', - escapedValue: 'beers > IPA > Brewdog punk IPA', - count: 6, - isRefined: false, - exhaustive: true, - data: null, - }, - ], - }, - { - name: 'Pale Ale', - path: 'beers > Pale Ale', - escapedValue: 'beers > Pale Ale', - count: 10, - isRefined: false, - exhaustive: true, - data: null, - }, - { - name: 'Stout', - path: 'beers > Stout', - escapedValue: 'beers > Stout', - count: 1, - isRefined: false, - exhaustive: true, - data: null, - }, + name: 'categories', + attributes: [ + 'categories.lvl0', + 'categories.lvl1', + 'categories.lvl2', + 'categories.lvl3', ], }, - { - name: 'fruits', - path: 'fruits', - escapedValue: 'fruits', - count: 5, - isRefined: false, - exhaustive: true, - data: null, - }, - { - name: 'sales', - path: 'sales', - escapedValue: 'sales', - count: 20, - isRefined: false, - exhaustive: true, - data: null, - }, ], - }, - ]; + }); - helper.setQuery('a').search(); + helper.toggleRefine('categories', 'beers > IPA > Flying dog'); - helper.once('result', function (event) { - var queries = client.search.mock.calls[0][0]; - var hitsQuery = queries[0]; - var parentValuesQuery = queries[1]; - var fullParentsValuesQueries = queries.slice(2); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 9, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'IPA', + path: 'beers > IPA', + escapedValue: 'beers > IPA', + count: 9, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'Flying dog', + path: 'beers > IPA > Flying dog', + escapedValue: 'beers > IPA > Flying dog', + count: 3, + isRefined: true, + exhaustive: true, + data: null, + }, + { + name: 'Brewdog punk IPA', + path: 'beers > IPA > Brewdog punk IPA', + escapedValue: 'beers > IPA > Brewdog punk IPA', + count: 6, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + { + name: 'Pale Ale', + path: 'beers > Pale Ale', + escapedValue: 'beers > Pale Ale', + count: 10, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'Stout', + path: 'beers > Stout', + escapedValue: 'beers > Stout', + count: 1, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + { + name: 'fruits', + path: 'fruits', + escapedValue: 'fruits', + count: 5, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'sales', + path: 'sales', + escapedValue: 'sales', + count: 20, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ]; - expect(queries.length).toBe(4); + helper.setQuery('a').search(); - expect(hitsQuery.params.facets).toEqual([ - 'categories.lvl0', - 'categories.lvl1', - 'categories.lvl2', - 'categories.lvl3', - ]); - expect(hitsQuery.params.facetFilters).toEqual([ - ['categories.lvl2:beers > IPA > Flying dog'], - ]); + helper.once('result', function (event) { + var queries = client.search.mock.calls[0][0]; + var hitsQuery = queries[0]; + var parentValuesQuery = queries[1]; + var fullParentsValuesQueries = queries.slice(2); - expect(parentValuesQuery.params.facets).toEqual([ - 'categories.lvl0', - 'categories.lvl1', - 'categories.lvl2', - ]); - expect(parentValuesQuery.params.facetFilters).toEqual([ - ['categories.lvl1:beers > IPA'], - ]); + expect(queries.length).toBe(4); - // Root - expect(fullParentsValuesQueries[0].params.facets).toEqual( - 'categories.lvl0' - ); - expect(fullParentsValuesQueries[0].params.facetFilters).toBe(undefined); + expect(hitsQuery.params.facets).toEqual([ + 'categories.lvl0', + 'categories.lvl1', + 'categories.lvl2', + 'categories.lvl3', + ]); + expect(hitsQuery.params.facetFilters).toEqual([ + ['categories.lvl2:beers > IPA > Flying dog'], + ]); - // Level 1 - expect(fullParentsValuesQueries[1].params.facets).toEqual( - 'categories.lvl1' - ); - expect(fullParentsValuesQueries[1].params.facetFilters).toEqual([ - 'categories.lvl0:beers', - ]); + expect(parentValuesQuery.params.facets).toEqual([ + 'categories.lvl0', + 'categories.lvl1', + 'categories.lvl2', + ]); + expect(parentValuesQuery.params.facetFilters).toEqual([ + ['categories.lvl1:beers > IPA'], + ]); - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - expect(event.results.getFacetByName('categories')).toEqual( - expectedHelperResponse[0] - ); + // Root + expect(fullParentsValuesQueries[0].params.facets).toEqual( + 'categories.lvl0' + ); + expect(fullParentsValuesQueries[0].params.facetFilters).toBe(undefined); + + // Level 1 + expect(fullParentsValuesQueries[1].params.facets).toEqual( + 'categories.lvl1' + ); + expect(fullParentsValuesQueries[1].params.facetFilters).toEqual([ + 'categories.lvl0:beers', + ]); + + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + expect(event.results.getFacetByName('categories')).toEqual( + expectedHelperResponse[0] + ); - // we do not yet support multiple values for hierarchicalFacetsRefinements - // but at some point we may want to open multiple leafs of a hierarchical menu - // So we set this as an array so that we do not have to bump major to handle it - expect( - Array.isArray(helper.state.hierarchicalFacetsRefinements.categories) - ).toBeTruthy(); - done(); + // we do not yet support multiple values for hierarchicalFacetsRefinements + // but at some point we may want to open multiple leafs of a hierarchical menu + // So we set this as an array so that we do not have to bump major to handle it + expect( + Array.isArray(helper.state.hierarchicalFacetsRefinements.categories) + ).toBeTruthy(); + done(); + }); }); }); - test('persistHierarchicalRootCount: true', function (done) { - var helper = algoliasearchHelper( - client, - indexName, - { - hierarchicalFacets: [ - { - name: 'categories', - attributes: [ - 'categories.lvl0', - 'categories.lvl1', - 'categories.lvl2', - 'categories.lvl3', - ], - }, - ], - }, - { - persistHierarchicalRootCount: true, - } - ); + test('persistHierarchicalRootCount: true', function () { + return new Promise(function (done) { + var helper = algoliasearchHelper( + client, + indexName, + { + hierarchicalFacets: [ + { + name: 'categories', + attributes: [ + 'categories.lvl0', + 'categories.lvl1', + 'categories.lvl2', + 'categories.lvl3', + ], + }, + ], + }, + { + persistHierarchicalRootCount: true, + } + ); - helper.toggleRefine('categories', 'beers > IPA > Flying dog'); + helper.toggleRefine('categories', 'beers > IPA > Flying dog'); - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ - { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 20, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'IPA', - path: 'beers > IPA', - escapedValue: 'beers > IPA', - count: 9, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'Flying dog', - path: 'beers > IPA > Flying dog', - escapedValue: 'beers > IPA > Flying dog', - count: 3, - isRefined: true, - exhaustive: true, - data: null, - }, - { - name: 'Brewdog punk IPA', - path: 'beers > IPA > Brewdog punk IPA', - escapedValue: 'beers > IPA > Brewdog punk IPA', - count: 6, - isRefined: false, - exhaustive: true, - data: null, - }, - ], - }, - { - name: 'Pale Ale', - path: 'beers > Pale Ale', - escapedValue: 'beers > Pale Ale', - count: 10, - isRefined: false, - exhaustive: true, - data: null, - }, - { - name: 'Stout', - path: 'beers > Stout', - escapedValue: 'beers > Stout', - count: 1, - isRefined: false, - exhaustive: true, - data: null, - }, - ], - }, - { - name: 'fruits', - path: 'fruits', - escapedValue: 'fruits', - count: 5, - isRefined: false, - exhaustive: true, - data: null, - }, - { - name: 'sales', - path: 'sales', - escapedValue: 'sales', - count: 20, - isRefined: false, - exhaustive: true, - data: null, - }, - ], - }, - ]; + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 20, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'IPA', + path: 'beers > IPA', + escapedValue: 'beers > IPA', + count: 9, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'Flying dog', + path: 'beers > IPA > Flying dog', + escapedValue: 'beers > IPA > Flying dog', + count: 3, + isRefined: true, + exhaustive: true, + data: null, + }, + { + name: 'Brewdog punk IPA', + path: 'beers > IPA > Brewdog punk IPA', + escapedValue: 'beers > IPA > Brewdog punk IPA', + count: 6, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + { + name: 'Pale Ale', + path: 'beers > Pale Ale', + escapedValue: 'beers > Pale Ale', + count: 10, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'Stout', + path: 'beers > Stout', + escapedValue: 'beers > Stout', + count: 1, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + { + name: 'fruits', + path: 'fruits', + escapedValue: 'fruits', + count: 5, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'sales', + path: 'sales', + escapedValue: 'sales', + count: 20, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ]; - helper.setQuery('a').search(); + helper.setQuery('a').search(); - helper.once('result', function (event) { - var queries = client.search.mock.calls[0][0]; - var hitsQuery = queries[0]; - var parentValuesQuery = queries[1]; - var fullParentsValuesQueries = queries.slice(2); + helper.once('result', function (event) { + var queries = client.search.mock.calls[0][0]; + var hitsQuery = queries[0]; + var parentValuesQuery = queries[1]; + var fullParentsValuesQueries = queries.slice(2); - expect(queries.length).toBe(4); + expect(queries.length).toBe(4); - expect(hitsQuery.params.facets).toEqual([ - 'categories.lvl0', - 'categories.lvl1', - 'categories.lvl2', - 'categories.lvl3', - ]); - expect(hitsQuery.params.facetFilters).toEqual([ - ['categories.lvl2:beers > IPA > Flying dog'], - ]); + expect(hitsQuery.params.facets).toEqual([ + 'categories.lvl0', + 'categories.lvl1', + 'categories.lvl2', + 'categories.lvl3', + ]); + expect(hitsQuery.params.facetFilters).toEqual([ + ['categories.lvl2:beers > IPA > Flying dog'], + ]); - expect(parentValuesQuery.params.facets).toEqual([ - 'categories.lvl0', - 'categories.lvl1', - 'categories.lvl2', - ]); - expect(parentValuesQuery.params.facetFilters).toEqual([ - ['categories.lvl1:beers > IPA'], - ]); + expect(parentValuesQuery.params.facets).toEqual([ + 'categories.lvl0', + 'categories.lvl1', + 'categories.lvl2', + ]); + expect(parentValuesQuery.params.facetFilters).toEqual([ + ['categories.lvl1:beers > IPA'], + ]); - // Root - expect(fullParentsValuesQueries[0].params.facets).toEqual( - 'categories.lvl0' - ); - expect(fullParentsValuesQueries[0].params.facetFilters).toBe(undefined); + // Root + expect(fullParentsValuesQueries[0].params.facets).toEqual( + 'categories.lvl0' + ); + expect(fullParentsValuesQueries[0].params.facetFilters).toBe(undefined); - // Level 1 - expect(fullParentsValuesQueries[1].params.facets).toEqual( - 'categories.lvl1' - ); - expect(fullParentsValuesQueries[1].params.facetFilters).toEqual([ - 'categories.lvl0:beers', - ]); + // Level 1 + expect(fullParentsValuesQueries[1].params.facets).toEqual( + 'categories.lvl1' + ); + expect(fullParentsValuesQueries[1].params.facetFilters).toEqual([ + 'categories.lvl0:beers', + ]); - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - expect(event.results.getFacetByName('categories')).toEqual( - expectedHelperResponse[0] - ); + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + expect(event.results.getFacetByName('categories')).toEqual( + expectedHelperResponse[0] + ); - // we do not yet support multiple values for hierarchicalFacetsRefinements - // but at some point we may want to open multiple leafs of a hierarchical menu - // So we set this as an array so that we do not have to bump major to handle it - expect( - Array.isArray(helper.state.hierarchicalFacetsRefinements.categories) - ).toBeTruthy(); - done(); + // we do not yet support multiple values for hierarchicalFacetsRefinements + // but at some point we may want to open multiple leafs of a hierarchical menu + // So we set this as an array so that we do not have to bump major to handle it + expect( + Array.isArray(helper.state.hierarchicalFacetsRefinements.categories) + ).toBeTruthy(); + done(); + }); }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/sort-by.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/sort-by.js index b04462f26a6..19db44f91c1 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/sort-by.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/sort-by.js @@ -1,150 +1,152 @@ 'use strict'; -test('hierarchical facets: using sortBy', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: using sortBy', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'categories', - attributes: [ - 'categories.lvl0', - 'categories.lvl1', - 'categories.lvl2', - 'categories.lvl3', - ], - sortBy: ['count:desc', 'name:asc'], - }, - ], - }); + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ + { + name: 'categories', + attributes: [ + 'categories.lvl0', + 'categories.lvl1', + 'categories.lvl2', + 'categories.lvl3', + ], + sortBy: ['count:desc', 'name:asc'], + }, + ], + }); - helper.toggleRefine('categories', 'beers > IPA > Flying dog'); + helper.toggleRefine('categories', 'beers > IPA > Flying dog'); - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'categories.lvl0': { beers: 1 }, - 'categories.lvl1': { 'beers > IPA': 1 }, - 'categories.lvl2': { 'beers > IPA > Flying dog': 1 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 5 }, - 'categories.lvl1': { 'beers > IPA': 5 }, - 'categories.lvl2': { - 'beers > IPA > Flying dog': 1, - 'beers > IPA > Anchor steam': 1, - 'beers > IPA > Brewdog punk IPA': 3, + var algoliaResponse = { + results: [ + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'categories.lvl0': { beers: 1 }, + 'categories.lvl1': { 'beers > IPA': 1 }, + 'categories.lvl2': { 'beers > IPA > Flying dog': 1 }, }, }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'categories.lvl0': { beers: 5 }, - }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'categories', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ { - name: 'beers', - path: 'beers', - escapedValue: 'beers', - count: 5, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'IPA', - path: 'beers > IPA', - escapedValue: 'beers > IPA', - count: 5, - isRefined: true, - exhaustive: true, - data: [ - { - name: 'Brewdog punk IPA', - path: 'beers > IPA > Brewdog punk IPA', - escapedValue: 'beers > IPA > Brewdog punk IPA', - count: 3, - isRefined: false, - exhaustive: true, - data: null, - }, - { - name: 'Anchor steam', - path: 'beers > IPA > Anchor steam', - escapedValue: 'beers > IPA > Anchor steam', - count: 1, - isRefined: false, - exhaustive: true, - data: null, - }, - { - name: 'Flying dog', - path: 'beers > IPA > Flying dog', - escapedValue: 'beers > IPA > Flying dog', - count: 1, - isRefined: true, - exhaustive: true, - data: null, - }, - ], + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 5 }, + 'categories.lvl1': { 'beers > IPA': 5 }, + 'categories.lvl2': { + 'beers > IPA > Flying dog': 1, + 'beers > IPA > Anchor steam': 1, + 'beers > IPA > Brewdog punk IPA': 3, }, - ], + }, + }, + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'categories.lvl0': { beers: 5 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'categories', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'beers', + path: 'beers', + escapedValue: 'beers', + count: 5, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'IPA', + path: 'beers > IPA', + escapedValue: 'beers > IPA', + count: 5, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'Brewdog punk IPA', + path: 'beers > IPA > Brewdog punk IPA', + escapedValue: 'beers > IPA > Brewdog punk IPA', + count: 3, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'Anchor steam', + path: 'beers > IPA > Anchor steam', + escapedValue: 'beers > IPA > Anchor steam', + count: 1, + isRefined: false, + exhaustive: true, + data: null, + }, + { + name: 'Flying dog', + path: 'beers > IPA > Flying dog', + escapedValue: 'beers > IPA > Flying dog', + count: 1, + isRefined: true, + exhaustive: true, + data: null, + }, + ], + }, + ], + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + helper.setQuery('a').search(); + helper.once('result', function (event) { + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/two-facets.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/two-facets.js index b1a9bdf6816..4b7e305ed1a 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/two-facets.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/two-facets.js @@ -1,141 +1,143 @@ 'use strict'; -test('hierarchical facets: two hierarchical facets', function (done) { - var algoliasearch = require('algoliasearch'); - algoliasearch = algoliasearch.algoliasearch || algoliasearch; +test('hierarchical facets: two hierarchical facets', function () { + return new Promise(function (done) { + var algoliasearch = require('algoliasearch'); + algoliasearch = algoliasearch.algoliasearch || algoliasearch; - var algoliasearchHelper = require('../../../'); + var algoliasearchHelper = require('../../../'); - var appId = 'hierarchical-simple-appId'; - var apiKey = 'hierarchical-simple-apiKey'; - var indexName = 'hierarchical-simple-indexName'; + var appId = 'hierarchical-simple-appId'; + var apiKey = 'hierarchical-simple-apiKey'; + var indexName = 'hierarchical-simple-indexName'; - var client = algoliasearch(appId, apiKey); - var helper = algoliasearchHelper(client, indexName, { - hierarchicalFacets: [ - { - name: 'beers', - attributes: ['beers.lvl0'], - }, - { - name: 'fruits', - attributes: ['fruits.lvl0'], - }, - ], - }); - - helper.toggleRefine('beers', 'IPA'); - helper.toggleRefine('fruits', 'oranges'); - - var algoliaResponse = { - results: [ - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 7, - page: 0, - nbPages: 1, - hitsPerPage: 20, - exhaustiveFacetsCount: true, - facets: { - 'beers.lvl0': { IPA: 2 }, - 'fruits.lvl0': { oranges: 5 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'beers.lvl0': { IPA: 2, Belgian: 3 }, - }, - }, - { - query: 'a', - index: indexName, - hits: [{ objectID: 'one' }], - nbHits: 1, - page: 0, - nbPages: 1, - hitsPerPage: 1, - facets: { - 'fruits.lvl0': { oranges: 5, apples: 4 }, - }, - }, - ], - }; - - var expectedHelperResponse = [ - { - name: 'beers', - count: null, - isRefined: true, - path: null, - escapedValue: null, - exhaustive: true, - data: [ + var client = algoliasearch(appId, apiKey); + var helper = algoliasearchHelper(client, indexName, { + hierarchicalFacets: [ { - name: 'IPA', - path: 'IPA', - escapedValue: 'IPA', - count: 2, - isRefined: true, - exhaustive: true, - data: null, + name: 'beers', + attributes: ['beers.lvl0'], }, { - name: 'Belgian', - path: 'Belgian', - escapedValue: 'Belgian', - count: 3, - isRefined: false, - exhaustive: true, - data: null, + name: 'fruits', + attributes: ['fruits.lvl0'], }, ], - }, - { - name: 'fruits', - path: null, - escapedValue: null, - count: null, - isRefined: true, - exhaustive: true, - data: [ + }); + + helper.toggleRefine('beers', 'IPA'); + helper.toggleRefine('fruits', 'oranges'); + + var algoliaResponse = { + results: [ + { + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 7, + page: 0, + nbPages: 1, + hitsPerPage: 20, + exhaustiveFacetsCount: true, + facets: { + 'beers.lvl0': { IPA: 2 }, + 'fruits.lvl0': { oranges: 5 }, + }, + }, { - name: 'oranges', - path: 'oranges', - escapedValue: 'oranges', - count: 5, - isRefined: true, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'beers.lvl0': { IPA: 2, Belgian: 3 }, + }, }, { - name: 'apples', - path: 'apples', - escapedValue: 'apples', - count: 4, - isRefined: false, - exhaustive: true, - data: null, + query: 'a', + index: indexName, + hits: [{ objectID: 'one' }], + nbHits: 1, + page: 0, + nbPages: 1, + hitsPerPage: 1, + facets: { + 'fruits.lvl0': { oranges: 5, apples: 4 }, + }, }, ], - }, - ]; + }; - client.search = jest.fn(function () { - return Promise.resolve(algoliaResponse); - }); + var expectedHelperResponse = [ + { + name: 'beers', + count: null, + isRefined: true, + path: null, + escapedValue: null, + exhaustive: true, + data: [ + { + name: 'IPA', + path: 'IPA', + escapedValue: 'IPA', + count: 2, + isRefined: true, + exhaustive: true, + data: null, + }, + { + name: 'Belgian', + path: 'Belgian', + escapedValue: 'Belgian', + count: 3, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + { + name: 'fruits', + path: null, + escapedValue: null, + count: null, + isRefined: true, + exhaustive: true, + data: [ + { + name: 'oranges', + path: 'oranges', + escapedValue: 'oranges', + count: 5, + isRefined: true, + exhaustive: true, + data: null, + }, + { + name: 'apples', + path: 'apples', + escapedValue: 'apples', + count: 4, + isRefined: false, + exhaustive: true, + data: null, + }, + ], + }, + ]; + + client.search = vi.fn(function () { + return Promise.resolve(algoliaResponse); + }); - helper.setQuery('a').search(); - helper.once('result', function (event) { - expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); - done(); + helper.setQuery('a').search(); + helper.once('result', function (event) { + expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse); + done(); + }); }); }); diff --git a/packages/algoliasearch-helper/test/spec/hierarchical-facets/with-a-disjunctive-facet.js b/packages/algoliasearch-helper/test/spec/hierarchical-facets/with-a-disjunctive-facet.js index d024beed048..840effd668c 100644 --- a/packages/algoliasearch-helper/test/spec/hierarchical-facets/with-a-disjunctive-facet.js +++ b/packages/algoliasearch-helper/test/spec/hierarchical-facets/with-a-disjunctive-facet.js @@ -24,7 +24,7 @@ test('hierarchical facets: combined with a disjunctive facet', function () { helper.toggleRefine('categories', 'beers > IPA'); helper.toggleRefine('colors', 'blue'); - client.search = jest.fn(function () { + client.search = vi.fn(function () { return new Promise(function () {}); }); diff --git a/packages/algoliasearch-helper/test/spec/recommend.js b/packages/algoliasearch-helper/test/spec/recommend.js index 585805c658f..cf42fbace18 100644 --- a/packages/algoliasearch-helper/test/spec/recommend.js +++ b/packages/algoliasearch-helper/test/spec/recommend.js @@ -3,92 +3,96 @@ var algoliasearchHelper = require('../../index'); describe('recommend()', () => { - test('calls the algolia client with the correct number of queries', (done) => { - var testData = - require('../datasets/RecommendParameters/recommend.dataset')(); - - var client = { - getRecommendations: jest.fn().mockImplementationOnce(() => { - return Promise.resolve(testData.response); - }), - }; - - var helper = algoliasearchHelper(client, 'indexName', {}); + test('calls the algolia client with the correct number of queries', () => { + return new Promise(function (done) { + var testData = + require('../datasets/RecommendParameters/recommend.dataset')(); - helper.addFrequentlyBoughtTogether({ - $$id: 1, - objectID: 'A0E20000000279B', - }); - helper.addFrequentlyBoughtTogether({ - $$id: 1, - objectID: 'A0E20000000279C', - }); - helper.addTrendingFacets({ $$id: 2, facetName: 'brand' }); - - // eslint-disable-next-line no-warning-comments - // TODO: listen to "result" event when events for Recommend are implemented - helper.on('recommend:result', (event) => { - var results = event.recommend.results; - // As it also includes '_state' and '_rawResults' - expect(Object.keys(results)).toHaveLength(4); - - // This one should be sorted - var hits = testData.response.results[0].hits; - expect(results[1].hits).toEqual([hits[1], hits[0], hits[2]]); - expect(results[2]).toBe(testData.response.results[2]); - - var state = event.recommend.state; - expect(state.params).toEqual(testData.recommendParams.params); - done(); - }); + var client = { + getRecommendations: vi.fn().mockImplementationOnce(() => { + return Promise.resolve(testData.response); + }), + }; - helper.recommend(); + var helper = algoliasearchHelper(client, 'indexName', {}); - expect(client.getRecommendations).toHaveBeenCalledTimes(1); - expect(client.getRecommendations).toHaveBeenCalledWith([ - { - indexName: 'indexName', - model: 'bought-together', + helper.addFrequentlyBoughtTogether({ + $$id: 1, objectID: 'A0E20000000279B', - threshold: 0, - }, - { - indexName: 'indexName', - model: 'bought-together', + }); + helper.addFrequentlyBoughtTogether({ + $$id: 1, objectID: 'A0E20000000279C', - threshold: 0, - }, - { - indexName: 'indexName', - model: 'trending-facets', - facetName: 'brand', - threshold: 0, - }, - ]); - }); - - test('triggers a fetch event', (done) => { - var client = { - getRecommendations: jest.fn().mockImplementationOnce(() => { - return Promise.resolve({ results: [] }); - }), - }; + }); + helper.addTrendingFacets({ $$id: 2, facetName: 'brand' }); + + // eslint-disable-next-line no-warning-comments + // TODO: listen to "result" event when events for Recommend are implemented + helper.on('recommend:result', (event) => { + var results = event.recommend.results; + // As it also includes '_state' and '_rawResults' + expect(Object.keys(results)).toHaveLength(4); + + // This one should be sorted + var hits = testData.response.results[0].hits; + expect(results[1].hits).toEqual([hits[1], hits[0], hits[2]]); + expect(results[2]).toBe(testData.response.results[2]); + + var state = event.recommend.state; + expect(state.params).toEqual(testData.recommendParams.params); + done(); + }); - var helper = algoliasearchHelper(client, 'indexName', {}); - helper.addTrendingFacets({ $$id: 2, facetName: 'brand' }); + helper.recommend(); - helper.on('fetch', (event) => { - var state = event.recommend.state; - expect(state).toEqual(helper.recommendState); - done(); + expect(client.getRecommendations).toHaveBeenCalledTimes(1); + expect(client.getRecommendations).toHaveBeenCalledWith([ + { + indexName: 'indexName', + model: 'bought-together', + objectID: 'A0E20000000279B', + threshold: 0, + }, + { + indexName: 'indexName', + model: 'bought-together', + objectID: 'A0E20000000279C', + threshold: 0, + }, + { + indexName: 'indexName', + model: 'trending-facets', + facetName: 'brand', + threshold: 0, + }, + ]); }); + }); - helper.recommend(); + test('triggers a fetch event', function () { + return new Promise(function (done) { + var client = { + getRecommendations: vi.fn().mockImplementationOnce(() => { + return Promise.resolve({ results: [] }); + }), + }; + + var helper = algoliasearchHelper(client, 'indexName', {}); + helper.addTrendingFacets({ $$id: 2, facetName: 'brand' }); + + helper.on('fetch', (event) => { + var state = event.recommend.state; + expect(state).toEqual(helper.recommendState); + done(); + }); + + helper.recommend(); + }); }); test('does not call the algolia client if there are no queries', () => { var client = { - getRecommendations: jest.fn().mockImplementationOnce(() => { + getRecommendations: vi.fn().mockImplementationOnce(() => { return Promise.resolve({ results: [] }); }), }; @@ -103,7 +107,7 @@ describe('recommend()', () => { var message = 'Please update algoliasearch/lite to the latest version in order to use recommend widgets.'; var client = {}; - console.warn = jest.fn(); + console.warn = vi.fn(); var helper = algoliasearchHelper(client, 'indexName', {}); helper.addFrequentlyBoughtTogether({ $$id: 1 }).recommend(); @@ -114,7 +118,7 @@ describe('recommend()', () => { test('is not called by mutating methods', () => { var client = { - getRecommendations: jest.fn().mockImplementationOnce(() => { + getRecommendations: vi.fn().mockImplementationOnce(() => { return Promise.resolve({ results: [] }); }), }; @@ -145,7 +149,7 @@ describe('recommend()', () => { require('../datasets/RecommendParameters/recommend.dataset')(); var client = { - getRecommendations: jest.fn().mockImplementation(() => { + getRecommendations: vi.fn().mockImplementation(() => { return Promise.resolve(testData.response); }), }; diff --git a/packages/algoliasearch-helper/test/spec/search.js b/packages/algoliasearch-helper/test/spec/search.js index 535f0df87ab..c6cb98783bf 100644 --- a/packages/algoliasearch-helper/test/spec/search.js +++ b/packages/algoliasearch-helper/test/spec/search.js @@ -2,120 +2,124 @@ var algoliasearchHelper = require('../../index'); -test('Search should call the algolia client according to the number of refinements', function (done) { - var testData = require('../datasets/SearchParameters/search.dataset')(); - - var client = { - search: jest.fn().mockImplementationOnce(function () { - return Promise.resolve(testData.response); - }), - }; - - var helper = algoliasearchHelper(client, 'test_hotels-node', { - disjunctiveFacets: ['city'], - }); - - helper.addDisjunctiveRefine('city', 'Paris', true); - helper.addDisjunctiveRefine('city', 'New York', true); - - helper.on('result', function (event) { - var results = event.results; - - // shame deepclone, to remove any associated methods coming from the results - expect(JSON.parse(JSON.stringify(results))).toEqual( - JSON.parse(JSON.stringify(testData.responseHelper)) - ); - - var cityValues = results.getFacetValues('city'); - var expectedCityValues = [ - { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, - { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, - { - name: 'San Francisco', - escapedValue: 'San Francisco', - count: 1, - isRefined: false, - }, - ]; - - expect(cityValues).toEqual(expectedCityValues); - - var cityValuesCustom = results.getFacetValues('city', { - sortBy: ['count:asc', 'name:asc'], +test('Search should call the algolia client according to the number of refinements', function () { + return new Promise(function (done) { + var testData = require('../datasets/SearchParameters/search.dataset')(); + + var client = { + search: vi.fn().mockImplementationOnce(function () { + return Promise.resolve(testData.response); + }), + }; + + var helper = algoliasearchHelper(client, 'test_hotels-node', { + disjunctiveFacets: ['city'], }); - var expectedCityValuesCustom = [ - { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, - { - name: 'San Francisco', - escapedValue: 'San Francisco', - count: 1, - isRefined: false, - }, - { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, - ]; - - expect(cityValuesCustom).toEqual(expectedCityValuesCustom); - - var cityValuesFn = results.getFacetValues('city', { - sortBy: function (a, b) { - return a.count - b.count; - }, + + helper.addDisjunctiveRefine('city', 'Paris', true); + helper.addDisjunctiveRefine('city', 'New York', true); + + helper.on('result', function (event) { + var results = event.results; + + // shame deepclone, to remove any associated methods coming from the results + expect(JSON.parse(JSON.stringify(results))).toEqual( + JSON.parse(JSON.stringify(testData.responseHelper)) + ); + + var cityValues = results.getFacetValues('city'); + var expectedCityValues = [ + { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, + { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, + { + name: 'San Francisco', + escapedValue: 'San Francisco', + count: 1, + isRefined: false, + }, + ]; + + expect(cityValues).toEqual(expectedCityValues); + + var cityValuesCustom = results.getFacetValues('city', { + sortBy: ['count:asc', 'name:asc'], + }); + var expectedCityValuesCustom = [ + { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, + { + name: 'San Francisco', + escapedValue: 'San Francisco', + count: 1, + isRefined: false, + }, + { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, + ]; + + expect(cityValuesCustom).toEqual(expectedCityValuesCustom); + + var cityValuesFn = results.getFacetValues('city', { + sortBy: function (a, b) { + return a.count - b.count; + }, + }); + var expectedCityValuesFn = [ + { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, + { + name: 'San Francisco', + escapedValue: 'San Francisco', + count: 1, + isRefined: false, + }, + { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, + ]; + + expect(cityValuesFn).toEqual(expectedCityValuesFn); + + expect(client.search).toHaveBeenCalledTimes(1); + + var queries = client.search.mock.calls[0][0]; + for (var i = 0; i < queries.length; i++) { + var query = queries[i]; + expect(query.query).toBeUndefined(); + expect(query.params.query).toBeUndefined(); + } + + done(); }); - var expectedCityValuesFn = [ - { name: 'New York', escapedValue: 'New York', count: 1, isRefined: true }, - { - name: 'San Francisco', - escapedValue: 'San Francisco', - count: 1, - isRefined: false, - }, - { name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true }, - ]; - - expect(cityValuesFn).toEqual(expectedCityValuesFn); - - expect(client.search).toHaveBeenCalledTimes(1); - - var queries = client.search.mock.calls[0][0]; - for (var i = 0; i < queries.length; i++) { - var query = queries[i]; - expect(query.query).toBeUndefined(); - expect(query.params.query).toBeUndefined(); - } - - done(); - }); - helper.search(''); + helper.search(''); + }); }); -test('Search should not mutate the original client response', function (done) { - var testData = require('../datasets/SearchParameters/search.dataset')(); +test('Search should not mutate the original client response', function () { + return new Promise(function (done) { + var testData = require('../datasets/SearchParameters/search.dataset')(); - var client = { - search: jest.fn().mockImplementationOnce(function () { - return Promise.resolve(testData.response); - }), - }; + var client = { + search: vi.fn().mockImplementationOnce(function () { + return Promise.resolve(testData.response); + }), + }; - var helper = algoliasearchHelper(client, 'test_hotels-node'); + var helper = algoliasearchHelper(client, 'test_hotels-node'); - var originalResponseLength = testData.response.results.length; + var originalResponseLength = testData.response.results.length; - helper.on('result', function () { - var currentResponseLength = testData.response.results.length; + helper.on('result', function () { + var currentResponseLength = testData.response.results.length; - expect(currentResponseLength).toBe(originalResponseLength); + expect(currentResponseLength).toBe(originalResponseLength); - done(); - }); + done(); + }); - helper.search(''); + helper.search(''); + }); }); test('no mutating methods should trigger a search', function () { var client = { - search: jest.fn().mockImplementationOnce(function () { + search: vi.fn().mockImplementationOnce(function () { return new Promise(function () {}); }), }; diff --git a/packages/algoliasearch-helper/test/spec/utils/sortAndMergeRecommendations.js b/packages/algoliasearch-helper/test/spec/utils/sortAndMergeRecommendations.js index beb8793a94a..ff401b86eef 100644 --- a/packages/algoliasearch-helper/test/spec/utils/sortAndMergeRecommendations.js +++ b/packages/algoliasearch-helper/test/spec/utils/sortAndMergeRecommendations.js @@ -86,44 +86,44 @@ test('sorts the items based on their average index thus preserving applied rules ); expect(result).toMatchInlineSnapshot(` - Array [ - Object { - "_score": 0, - "name": "Product B", - "objectID": "B", - }, - Object { - "_score": 76, - "name": "Product E", - "objectID": "E", - }, - Object { - "_score": 0, - "name": "Product C", - "objectID": "C", - }, - Object { - "_score": 100, - "name": "Product F", - "objectID": "F", - }, - Object { - "_score": 100, - "name": "Product A", - "objectID": "A", - }, - Object { - "_score": 96, - "name": "Product G", - "objectID": "G", - }, - Object { - "_score": 89, - "name": "Product D", - "objectID": "D", - }, - ] - `); + [ + { + "_score": 0, + "name": "Product B", + "objectID": "B", + }, + { + "_score": 76, + "name": "Product E", + "objectID": "E", + }, + { + "_score": 0, + "name": "Product C", + "objectID": "C", + }, + { + "_score": 100, + "name": "Product F", + "objectID": "F", + }, + { + "_score": 100, + "name": "Product A", + "objectID": "A", + }, + { + "_score": 96, + "name": "Product G", + "objectID": "G", + }, + { + "_score": 89, + "name": "Product D", + "objectID": "D", + }, + ] + `); }); test('filters out input objectIDs', () => { @@ -135,27 +135,27 @@ test('filters out input objectIDs', () => { ); expect(result).toMatchInlineSnapshot(` - Array [ - Object { - "_score": 76, - "name": "Product E", - "objectID": "E", - }, - Object { - "_score": 100, - "name": "Product F", - "objectID": "F", - }, - Object { - "_score": 96, - "name": "Product G", - "objectID": "G", - }, - Object { - "_score": 89, - "name": "Product D", - "objectID": "D", - }, - ] - `); + [ + { + "_score": 76, + "name": "Product E", + "objectID": "E", + }, + { + "_score": 100, + "name": "Product F", + "objectID": "F", + }, + { + "_score": 96, + "name": "Product G", + "objectID": "G", + }, + { + "_score": 89, + "name": "Product D", + "objectID": "D", + }, + ] + `); }); diff --git a/packages/algoliasearch-helper/vitest.config.ts b/packages/algoliasearch-helper/vitest.config.ts new file mode 100644 index 00000000000..bdd24623b06 --- /dev/null +++ b/packages/algoliasearch-helper/vitest.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['test/spec/**/*.[jt]s?(x)'], + dangerouslyIgnoreUnhandledErrors: true, + }, +}); diff --git a/packages/algoliasearch-helper/vitest.setup.ts b/packages/algoliasearch-helper/vitest.setup.ts new file mode 100644 index 00000000000..9d1c55e0bc5 --- /dev/null +++ b/packages/algoliasearch-helper/vitest.setup.ts @@ -0,0 +1,3 @@ +import { vi } from 'vitest'; + +vi.setConfig({ testTimeout: 20000 }); diff --git a/packages/create-instantsearch-app/.eslintrc.js b/packages/create-instantsearch-app/.eslintrc.js index bfd3a913d9c..d59516eb1ce 100644 --- a/packages/create-instantsearch-app/.eslintrc.js +++ b/packages/create-instantsearch-app/.eslintrc.js @@ -1,5 +1,5 @@ module.exports = { - extends: ['algolia', 'algolia/jest'], + extends: ['algolia', 'plugin:vitest/recommended'], rules: { 'import/no-commonjs': 'off', 'no-console': 'off', diff --git a/packages/create-instantsearch-app/e2e/__snapshots__/templates.test.js.snap b/packages/create-instantsearch-app/e2e/__snapshots__/templates.test.js.snap index e89951ad7e4..ea7bd642c4c 100644 --- a/packages/create-instantsearch-app/e2e/__snapshots__/templates.test.js.snap +++ b/packages/create-instantsearch-app/e2e/__snapshots__/templates.test.js.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`Templates Autocomplete File content: .editorconfig 1`] = ` +exports[`Templates > Autocomplete > File content > .editorconfig 1`] = ` "root = true [*] @@ -12,13 +12,13 @@ insert_final_newline = true trim_trailing_whitespace = true" `; -exports[`Templates Autocomplete File content: .eslintignore 1`] = ` +exports[`Templates > Autocomplete > File content > .eslintignore 1`] = ` "/node_modules /dist /.cache" `; -exports[`Templates Autocomplete File content: .eslintrc.js 1`] = ` +exports[`Templates > Autocomplete > File content > .eslintrc.js 1`] = ` "/* eslint-disable import/no-commonjs */ module.exports = { @@ -41,7 +41,7 @@ module.exports = { };" `; -exports[`Templates Autocomplete File content: .gitignore 1`] = ` +exports[`Templates > Autocomplete > File content > .gitignore 1`] = ` "# See https://help.github.com/ignore-files/ for more about ignoring files. # dependencies @@ -66,15 +66,15 @@ yarn-debug.log* yarn-error.log*" `; -exports[`Templates Autocomplete File content: .prettierrc 1`] = ` +exports[`Templates > Autocomplete > File content > .prettierrc 1`] = ` "{ - \\"singleQuote\\": true, - \\"proseWrap\\": \\"never\\", - \\"trailingComma\\": \\"es5\\" + "singleQuote": true, + "proseWrap": "never", + "trailingComma": "es5" }" `; -exports[`Templates Autocomplete File content: README.md 1`] = ` +exports[`Templates > Autocomplete > File content > README.md 1`] = ` "# autocomplete-app _This project was generated with [create-instantsearch-app](https://github.com/algolia/instantsearch/tree/master/packages/create-instantsearch-app) by [Algolia](https://algolia.com)._ @@ -98,7 +98,7 @@ yarn start Open http://localhost:3000 to see your app." `; -exports[`Templates Autocomplete File content: app.js 1`] = ` +exports[`Templates > Autocomplete > File content > app.js 1`] = ` "/** @jsx h */ import { autocomplete, getAlgoliaResults } from '@algolia/autocomplete-js'; import algoliasearch from 'algoliasearch'; @@ -130,13 +130,13 @@ autocomplete({ templates: { item({ item, components }) { return ( -
-
-
-
+
+
+
+
@@ -154,68 +154,68 @@ autocomplete({ });" `; -exports[`Templates Autocomplete File content: index.html 1`] = ` -" +exports[`Templates > Autocomplete > File content > index.html 1`] = ` +" - - + + - - + + autocomplete-app -
-
+
+
- + " `; -exports[`Templates Autocomplete File content: manifest.webmanifest 1`] = ` +exports[`Templates > Autocomplete > File content > manifest.webmanifest 1`] = ` "{ - \\"short_name\\": \\"autocomplete-app\\", - \\"name\\": \\"autocomplete-app Sample\\", - \\"icons\\": [ + "short_name": "autocomplete-app", + "name": "autocomplete-app Sample", + "icons": [ { - \\"src\\": \\"favicon.png\\", - \\"sizes\\": \\"64x64 32x32 24x24 16x16\\", - \\"type\\": \\"image/x-icon\\" + "src": "favicon.png", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" } ], - \\"start_url\\": \\"./index.html\\", - \\"display\\": \\"standalone\\", - \\"theme_color\\": \\"#000000\\", - \\"background_color\\": \\"#ffffff\\" + "start_url": "./index.html", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" }" `; -exports[`Templates Autocomplete File content: package.json 1`] = ` +exports[`Templates > Autocomplete > File content > package.json 1`] = ` "{ - \\"name\\": \\"autocomplete-app\\", - \\"version\\": \\"1.0.0\\", - \\"private\\": true, - \\"scripts\\": { - \\"build\\": \\"parcel build index.html\\", - \\"start\\": \\"parcel index.html --port 3000\\", - \\"lint\\": \\"eslint .\\" + "name": "autocomplete-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "parcel build index.html", + "start": "parcel index.html --port 3000", + "lint": "eslint ." }, - \\"keywords\\": [ - \\"algolia\\", - \\"autocomplete\\", - \\"javascript\\" + "keywords": [ + "algolia", + "autocomplete", + "javascript" ], - \\"partialDependencies\\": { - \\"@algolia/autocomplete-js\\": \\"1.0.0\\" + "partialDependencies": { + "@algolia/autocomplete-js": "1.0.0" } }" `; -exports[`Templates Autocomplete File content: style.css 1`] = ` +exports[`Templates > Autocomplete > File content > style.css 1`] = ` "* { box-sizing: border-box; } @@ -238,8 +238,8 @@ body { }" `; -exports[`Templates Autocomplete Folder structure: contains the right files 1`] = ` -Array [ +exports[`Templates > Autocomplete > Folder structure > contains the right files 1`] = ` +[ ".editorconfig", ".eslintignore", ".eslintrc.js", @@ -255,7 +255,7 @@ Array [ ] `; -exports[`Templates InstantSearch Android File content: .gitignore 1`] = ` +exports[`Templates > InstantSearch Android > File content > .gitignore 1`] = ` "# IDE Files *.iml .idea/* @@ -275,9 +275,9 @@ projectFilesBackup .DS_Store" `; -exports[`Templates InstantSearch Android File content: app/.gitignore 1`] = `"/build"`; +exports[`Templates > InstantSearch Android > File content > app/.gitignore 1`] = `"/build"`; -exports[`Templates InstantSearch Android File content: app/build.gradle 1`] = ` +exports[`Templates > InstantSearch Android > File content > app/build.gradle 1`] = ` "apply plugin: 'com.android.application' android { @@ -285,12 +285,12 @@ android { compileSdkVersion 27 buildToolsVersion '27.0.3' defaultConfig { - applicationId \\"com.example.instantsearch.app\\" + applicationId "com.example.instantsearch.app" minSdkVersion 15 targetSdkVersion 27 versionCode 1 - versionName \\"1.0\\" - testInstrumentationRunner \\"android.support.test.runner.AndroidJUnitRunner\\" + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { @@ -312,7 +312,7 @@ dependencies { }" `; -exports[`Templates InstantSearch Android File content: app/proguard-rules.pro 1`] = ` +exports[`Templates > InstantSearch Android > File content > app/proguard-rules.pro 1`] = ` "# Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /Users/pln/Library/Android/sdk/tools/proguard/proguard-android.txt @@ -340,7 +340,7 @@ exports[`Templates InstantSearch Android File content: app/proguard-rules.pro 1` #-renamesourcefileattribute SourceFile" `; -exports[`Templates InstantSearch Android File content: app/src/androidTest/java/com/example/instantsearch/app/ExampleInstrumentedTest.java 1`] = ` +exports[`Templates > InstantSearch Android > File content > app/src/androidTest/java/com/example/instantsearch/app/ExampleInstrumentedTest.java 1`] = ` "package com.example.instantsearch.app; import android.content.Context; @@ -355,7 +355,7 @@ import static org.junit.Assert.*; /** * Instrumentation test, which will execute on an Android device. * - * @see Testing documentation + * @see Testing documentation */ @RunWith(AndroidJUnit4.class) public class ExampleInstrumentedTest { @@ -364,28 +364,28 @@ public class ExampleInstrumentedTest { // Context of the app under test. Context appContext = InstrumentationRegistry.getTargetContext(); - assertEquals(\\"com.example.instantsearch.app\\", appContext.getPackageName()); + assertEquals("com.example.instantsearch.app", appContext.getPackageName()); } }" `; -exports[`Templates InstantSearch Android File content: app/src/main/AndroidManifest.xml 1`] = ` -" - +exports[`Templates > InstantSearch Android > File content > app/src/main/AndroidManifest.xml 1`] = ` +" + - + android:allowBackup="true" + android:icon="@mipmap/ic_launcher" + android:label="@string/app_name" + android:roundIcon="@mipmap/ic_launcher_round" + android:supportsRtl="true" + android:theme="@style/AppTheme"> + - + - + @@ -393,7 +393,7 @@ exports[`Templates InstantSearch Android File content: app/src/main/AndroidManif " `; -exports[`Templates InstantSearch Android File content: app/src/main/java/com/example/instantsearch/app/MainActivity.java 1`] = ` +exports[`Templates > InstantSearch Android > File content > app/src/main/java/com/example/instantsearch/app/MainActivity.java 1`] = ` "package com.example.instantsearch.app; import android.os.Bundle; @@ -403,9 +403,9 @@ import com.algolia.instantsearch.helpers.Searcher; import com.algolia.instantsearch.helpers.InstantSearch; public class MainActivity extends AppCompatActivity { - private static final String ALGOLIA_APP_ID = \\"appId\\"; - private static final String ALGOLIA_SEARCH_API_KEY = \\"apiKey\\"; - private static final String ALGOLIA_INDEX_NAME = \\"indexName\\"; + private static final String ALGOLIA_APP_ID = "appId"; + private static final String ALGOLIA_SEARCH_API_KEY = "apiKey"; + private static final String ALGOLIA_INDEX_NAME = "indexName"; @Override protected void onCreate(Bundle savedInstanceState) { @@ -418,115 +418,115 @@ public class MainActivity extends AppCompatActivity { }" `; -exports[`Templates InstantSearch Android File content: app/src/main/res/layout/activity_main.xml 1`] = ` -" +exports[`Templates > InstantSearch Android > File content > app/src/main/res/layout/activity_main.xml 1`] = ` +" + android:id="@+id/activity_main" + xmlns:algolia="http://schemas.android.com/apk/res-auto" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + tools:context="com.example.instantsearch.app.MainActivity"> + android:id="@+id/search_box" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp"/> + android:id="@+id/hits" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/search_box" + algolia:itemLayout="@layout/hits_item"/> " `; -exports[`Templates InstantSearch Android File content: app/src/main/res/layout/hits_item.xml 1`] = ` -" +exports[`Templates > InstantSearch Android > File content > app/src/main/res/layout/hits_item.xml 1`] = ` +" + android:id="@+id/attribute1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="attribute1" + android:textSize="20sp" + android:textStyle="bold" + algolia:attribute='@{"attribute1"}' + algolia:highlightColor="@color/colorAccent" + algolia:highlighted="@{true}"/> " `; -exports[`Templates InstantSearch Android File content: app/src/main/res/values/colors.xml 1`] = ` -" +exports[`Templates > InstantSearch Android > File content > app/src/main/res/values/colors.xml 1`] = ` +" - #3F51B5 - #303F9F - #FF4081 + #3F51B5 + #303F9F + #FF4081 " `; -exports[`Templates InstantSearch Android File content: app/src/main/res/values/strings.xml 1`] = ` +exports[`Templates > InstantSearch Android > File content > app/src/main/res/values/strings.xml 1`] = ` " - instantsearch-android-app + instantsearch-android-app " `; -exports[`Templates InstantSearch Android File content: app/src/main/res/values/styles.xml 1`] = ` +exports[`Templates > InstantSearch Android > File content > app/src/main/res/values/styles.xml 1`] = ` " - " `; -exports[`Templates InstantSearch Android File content: build.gradle 1`] = ` +exports[`Templates > InstantSearch Android > File content > build.gradle 1`] = ` "// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { @@ -554,7 +554,7 @@ task clean(type: Delete) { }" `; -exports[`Templates InstantSearch Android File content: gradle.properties 1`] = ` +exports[`Templates > InstantSearch Android > File content > gradle.properties 1`] = ` "# Project-wide Gradle settings. # IDE (e.g. Android Studio) users: @@ -574,16 +574,16 @@ org.gradle.jvmargs=-Xmx1536m # org.gradle.parallel=true" `; -exports[`Templates InstantSearch Android File content: gradle/wrapper/gradle-wrapper.properties 1`] = ` +exports[`Templates > InstantSearch Android > File content > gradle/wrapper/gradle-wrapper.properties 1`] = ` "#Tue Jul 03 16:02:11 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\\\\://services.gradle.org/distributions/gradle-5.6-all.zip" +distributionUrl=https\\://services.gradle.org/distributions/gradle-5.6-all.zip" `; -exports[`Templates InstantSearch Android File content: gradlew 1`] = ` +exports[`Templates > InstantSearch Android > File content > gradlew 1`] = ` "#!/usr/bin/env bash ############################################################################## @@ -593,21 +593,21 @@ exports[`Templates InstantSearch Android File content: gradlew 1`] = ` ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS=\\"\\" +DEFAULT_JVM_OPTS="" -APP_NAME=\\"Gradle\\" -APP_BASE_NAME=\`basename \\"$0\\"\` +APP_NAME="Gradle" +APP_BASE_NAME=\`basename "$0"\` # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=\\"maximum\\" +MAX_FD="maximum" warn ( ) { - echo \\"$*\\" + echo "$*" } die ( ) { echo - echo \\"$*\\" + echo "$*" echo exit 1 } @@ -616,7 +616,7 @@ die ( ) { cygwin=false msys=false darwin=false -case \\"\`uname\`\\" in +case "\`uname\`" in CYGWIN* ) cygwin=true ;; @@ -630,124 +630,124 @@ esac # Attempt to set APP_HOME # Resolve links: $0 may be a link -PRG=\\"$0\\" +PRG="$0" # Need this for relative symlinks. -while [ -h \\"$PRG\\" ] ; do - ls=\`ls -ld \\"$PRG\\"\` - link=\`expr \\"$ls\\" : '.*-> \\\\(.*\\\\)$'\` - if expr \\"$link\\" : '/.*' > /dev/null; then - PRG=\\"$link\\" +while [ -h "$PRG" ] ; do + ls=\`ls -ld "$PRG"\` + link=\`expr "$ls" : '.*-> \\(.*\\)$'\` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" else - PRG=\`dirname \\"$PRG\\"\`\\"/$link\\" + PRG=\`dirname "$PRG"\`"/$link" fi done -SAVED=\\"\`pwd\`\\" -cd \\"\`dirname \\\\\\"$PRG\\\\\\"\`/\\" >/dev/null -APP_HOME=\\"\`pwd -P\`\\" -cd \\"$SAVED\\" >/dev/null +SAVED="\`pwd\`" +cd "\`dirname \\"$PRG\\"\`/" >/dev/null +APP_HOME="\`pwd -P\`" +cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. -if [ -n \\"$JAVA_HOME\\" ] ; then - if [ -x \\"$JAVA_HOME/jre/sh/java\\" ] ; then +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=\\"$JAVA_HOME/jre/sh/java\\" + JAVACMD="$JAVA_HOME/jre/sh/java" else - JAVACMD=\\"$JAVA_HOME/bin/java\\" + JAVACMD="$JAVA_HOME/bin/java" fi - if [ ! -x \\"$JAVACMD\\" ] ; then - die \\"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the -location of your Java installation.\\" +location of your Java installation." fi else - JAVACMD=\\"java\\" - which java >/dev/null 2>&1 || die \\"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the -location of your Java installation.\\" +location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ \\"$cygwin\\" = \\"false\\" -a \\"$darwin\\" = \\"false\\" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=\`ulimit -H -n\` if [ $? -eq 0 ] ; then - if [ \\"$MAX_FD\\" = \\"maximum\\" -o \\"$MAX_FD\\" = \\"max\\" ] ; then - MAX_FD=\\"$MAX_FD_LIMIT\\" + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then - warn \\"Could not set maximum file descriptor limit: $MAX_FD\\" + warn "Could not set maximum file descriptor limit: $MAX_FD" fi else - warn \\"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\\" + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then - GRADLE_OPTS=\\"$GRADLE_OPTS \\\\\\"-Xdock:name=$APP_NAME\\\\\\" \\\\\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\\\\"\\" + GRADLE_OPTS="$GRADLE_OPTS \\"-Xdock:name=$APP_NAME\\" \\"-Xdock:icon=$APP_HOME/media/gradle.icns\\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then - APP_HOME=\`cygpath --path --mixed \\"$APP_HOME\\"\` - CLASSPATH=\`cygpath --path --mixed \\"$CLASSPATH\\"\` - JAVACMD=\`cygpath --unix \\"$JAVACMD\\"\` + APP_HOME=\`cygpath --path --mixed "$APP_HOME"\` + CLASSPATH=\`cygpath --path --mixed "$CLASSPATH"\` + JAVACMD=\`cygpath --unix "$JAVACMD"\` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=\`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null\` - SEP=\\"\\" + SEP="" for dir in $ROOTDIRSRAW ; do - ROOTDIRS=\\"$ROOTDIRS$SEP$dir\\" - SEP=\\"|\\" + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" done - OURCYGPATTERN=\\"(^($ROOTDIRS))\\" + OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments - if [ \\"$GRADLE_CYGPATTERN\\" != \\"\\" ] ; then - OURCYGPATTERN=\\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\\" + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 - for arg in \\"$@\\" ; do - CHECK=\`echo \\"$arg\\"|egrep -c \\"$OURCYGPATTERN\\" -\` - CHECK2=\`echo \\"$arg\\"|egrep -c \\"^-\\"\` ### Determine if an option + for arg in "$@" ; do + CHECK=\`echo "$arg"|egrep -c "$OURCYGPATTERN" -\` + CHECK2=\`echo "$arg"|egrep -c "^-"\` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval \`echo args$i\`=\`cygpath --path --ignore --mixed \\"$arg\\"\` + eval \`echo args$i\`=\`cygpath --path --ignore --mixed "$arg"\` else - eval \`echo args$i\`=\\"\\\\\\"$arg\\\\\\"\\" + eval \`echo args$i\`="\\"$arg\\"" fi i=$((i+1)) done case $i in (0) set -- ;; - (1) set -- \\"$args0\\" ;; - (2) set -- \\"$args0\\" \\"$args1\\" ;; - (3) set -- \\"$args0\\" \\"$args1\\" \\"$args2\\" ;; - (4) set -- \\"$args0\\" \\"$args1\\" \\"$args2\\" \\"$args3\\" ;; - (5) set -- \\"$args0\\" \\"$args1\\" \\"$args2\\" \\"$args3\\" \\"$args4\\" ;; - (6) set -- \\"$args0\\" \\"$args1\\" \\"$args2\\" \\"$args3\\" \\"$args4\\" \\"$args5\\" ;; - (7) set -- \\"$args0\\" \\"$args1\\" \\"$args2\\" \\"$args3\\" \\"$args4\\" \\"$args5\\" \\"$args6\\" ;; - (8) set -- \\"$args0\\" \\"$args1\\" \\"$args2\\" \\"$args3\\" \\"$args4\\" \\"$args5\\" \\"$args6\\" \\"$args7\\" ;; - (9) set -- \\"$args0\\" \\"$args1\\" \\"$args2\\" \\"$args3\\" \\"$args4\\" \\"$args5\\" \\"$args6\\" \\"$args7\\" \\"$args8\\" ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { - JVM_OPTS=(\\"$@\\") + JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[\${#JVM_OPTS[*]}]=\\"-Dorg.gradle.appname=$APP_BASE_NAME\\" +JVM_OPTS[\${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" -exec \\"$JAVACMD\\" \\"\${JVM_OPTS[@]}\\" -classpath \\"$CLASSPATH\\" org.gradle.wrapper.GradleWrapperMain \\"$@\\"" +exec "$JAVACMD" "\${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"" `; -exports[`Templates InstantSearch Android File content: gradlew.bat 1`] = ` -"@if \\"%DEBUG%\\" == \\"\\" @echo off +exports[`Templates > InstantSearch Android > File content > gradlew.bat 1`] = ` +"@if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -755,13 +755,13 @@ exports[`Templates InstantSearch Android File content: gradlew.bat 1`] = ` @rem ########################################################################## @rem Set local scope for the variables with windows NT shell -if \\"%OS%\\"==\\"Windows_NT\\" setlocal +if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= set DIRNAME=%~dp0 -if \\"%DIRNAME%\\" == \\"\\" set DIRNAME=. +if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -770,7 +770,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if \\"%ERRORLEVEL%\\" == \\"0\\" goto init +if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -781,10 +781,10 @@ echo location of your Java installation. goto fail :findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:\\"=% +set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist \\"%JAVA_EXE%\\" goto init +if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -797,8 +797,8 @@ goto fail :init @rem Get command-line arguments, handling Windowz variants -if not \\"%OS%\\" == \\"Windows_NT\\" goto win9xME_args -if \\"%@eval[2+2]\\" == \\"4\\" goto 4NT_args +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -806,7 +806,7 @@ set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp -if \\"x%~1\\" == \\"x\\" goto execute +if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* goto execute @@ -818,31 +818,31 @@ set CMD_LINE_ARGS=%$ :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\\\\gradle\\\\wrapper\\\\gradle-wrapper.jar +set CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar @rem Execute Gradle -\\"%JAVA_EXE%\\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \\"-Dorg.gradle.appname=%APP_BASE_NAME%\\" -classpath \\"%CLASSPATH%\\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell -if \\"%ERRORLEVEL%\\"==\\"0\\" goto mainEnd +if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not \\"\\" == \\"%GRADLE_EXIT_CONSOLE%\\" exit 1 +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd -if \\"%OS%\\"==\\"Windows_NT\\" endlocal +if "%OS%"=="Windows_NT" endlocal :omega" `; -exports[`Templates InstantSearch Android File content: settings.gradle 1`] = `"include ':app'"`; +exports[`Templates > InstantSearch Android > File content > settings.gradle 1`] = `"include ':app'"`; -exports[`Templates InstantSearch Android Folder structure: contains the right files 1`] = ` -Array [ +exports[`Templates > InstantSearch Android > Folder structure > contains the right files 1`] = ` +[ ".gitignore", "app/.gitignore", "app/build.gradle", @@ -875,7 +875,7 @@ Array [ ] `; -exports[`Templates InstantSearch iOS File content: .gitignore 1`] = ` +exports[`Templates > InstantSearch iOS > File content > .gitignore 1`] = ` "# Created by https://www.gitignore.io/api/swift ### Swift ### @@ -948,7 +948,7 @@ fastlane/test_output # End of https://www.gitignore.io/api/swift" `; -exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj 1`] = ` +exports[`Templates > InstantSearch iOS > File content > App.xcodeproj/project.pbxproj 1`] = ` "// !$*UTF8*$! { archiveVersion = 1; @@ -967,16 +967,16 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 7B3645EFB63597C820FD0759 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \\"Pods-App.release.xcconfig\\"; path = \\"Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig\\"; sourceTree = \\"\\"; }; - B7E0369A70FFFFD97E30AF6C /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \\"Pods-App.debug.xcconfig\\"; path = \\"Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig\\"; sourceTree = \\"\\"; }; + 7B3645EFB63597C820FD0759 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = ""; }; + B7E0369A70FFFFD97E30AF6C /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = ""; }; E045BD52917EA4B39612E12B /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E258C9231EE036970076097D /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = \\"App.app\\"; sourceTree = BUILT_PRODUCTS_DIR; }; - E258C9261EE036970076097D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \\"\\"; }; - E258C9281EE036970076097D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = \\"\\"; }; - E258C92B1EE036970076097D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \\"\\"; }; - E258C92D1EE036970076097D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \\"\\"; }; - E258C9301EE036970076097D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \\"\\"; }; - E258C9321EE036970076097D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \\"\\"; }; + E258C9231EE036970076097D /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + E258C9261EE036970076097D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + E258C9281EE036970076097D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + E258C92B1EE036970076097D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + E258C92D1EE036970076097D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + E258C9301EE036970076097D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + E258C9321EE036970076097D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -998,7 +998,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj 7B3645EFB63597C820FD0759 /* Pods-App.release.xcconfig */, ); name = Pods; - sourceTree = \\"\\"; + sourceTree = ""; }; D3097422C732829DA51DBC25 /* Frameworks */ = { isa = PBXGroup; @@ -1006,7 +1006,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj E045BD52917EA4B39612E12B /* Pods_App.framework */, ); name = Frameworks; - sourceTree = \\"\\"; + sourceTree = ""; }; E258C91A1EE036970076097D = { isa = PBXGroup; @@ -1016,7 +1016,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj 5188048A03FF48C89161FB44 /* Pods */, D3097422C732829DA51DBC25 /* Frameworks */, ); - sourceTree = \\"\\"; + sourceTree = ""; }; E258C9241EE036970076097D /* Products */ = { isa = PBXGroup; @@ -1024,7 +1024,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj E258C9231EE036970076097D /* App.app */, ); name = Products; - sourceTree = \\"\\"; + sourceTree = ""; }; E258C9251EE036970076097D /* App */ = { isa = PBXGroup; @@ -1036,15 +1036,15 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj E258C92F1EE036970076097D /* LaunchScreen.storyboard */, E258C9321EE036970076097D /* Info.plist */, ); - path = \\"App\\"; - sourceTree = \\"\\"; + path = "App"; + sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ E258C9221EE036970076097D /* App */ = { isa = PBXNativeTarget; - buildConfigurationList = E258C9351EE036970076097D /* Build configuration list for PBXNativeTarget \\"App\\" */; + buildConfigurationList = E258C9351EE036970076097D /* Build configuration list for PBXNativeTarget "App" */; buildPhases = ( 6ED659C468517EE7AE9D6746 /* [CP] Check Pods Manifest.lock */, E258C91F1EE036970076097D /* Sources */, @@ -1056,10 +1056,10 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj ); dependencies = ( ); - name = \\"App\\"; - productName = \\"App\\"; + name = "App"; + productName = "App"; productReference = E258C9231EE036970076097D /* App.app */; - productType = \\"com.apple.product-type.application\\"; + productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -1069,7 +1069,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj attributes = { LastSwiftUpdateCheck = 0830; LastUpgradeCheck = 0830; - ORGANIZATIONNAME = \\"Guy Daher\\"; + ORGANIZATIONNAME = "Guy Daher"; TargetAttributes = { E258C9221EE036970076097D = { CreatedOnToolsVersion = 8.3.2; @@ -1078,8 +1078,8 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj }; }; }; - buildConfigurationList = E258C91E1EE036970076097D /* Build configuration list for PBXProject \\"App\\" */; - compatibilityVersion = \\"Xcode 3.2\\"; + buildConfigurationList = E258C91E1EE036970076097D /* Build configuration list for PBXProject "App" */; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( @@ -1088,8 +1088,8 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj ); mainGroup = E258C91A1EE036970076097D; productRefGroup = E258C9241EE036970076097D /* Products */; - projectDirPath = \\"\\"; - projectRoot = \\"\\"; + projectDirPath = ""; + projectRoot = ""; targets = ( E258C9221EE036970076097D /* App */, ); @@ -1116,20 +1116,20 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj files = ( ); inputPaths = ( - \\"\${SRCROOT}/Pods/Target Support Files/Pods-App/Pods-App-frameworks.sh\\", - \\"\${BUILT_PRODUCTS_DIR}/InstantSearch/InstantSearch.framework\\", - \\"\${BUILT_PRODUCTS_DIR}/InstantSearchClient/InstantSearchClient.framework\\", - \\"\${BUILT_PRODUCTS_DIR}/InstantSearchCore/InstantSearchCore.framework\\", + "\${SRCROOT}/Pods/Target Support Files/Pods-App/Pods-App-frameworks.sh", + "\${BUILT_PRODUCTS_DIR}/InstantSearch/InstantSearch.framework", + "\${BUILT_PRODUCTS_DIR}/InstantSearchClient/InstantSearchClient.framework", + "\${BUILT_PRODUCTS_DIR}/InstantSearchCore/InstantSearchCore.framework", ); - name = \\"[CP] Embed Pods Frameworks\\"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - \\"\${TARGET_BUILD_DIR}/\${FRAMEWORKS_FOLDER_PATH}/InstantSearch.framework\\", - \\"\${TARGET_BUILD_DIR}/\${FRAMEWORKS_FOLDER_PATH}/InstantSearchClient.framework\\", - \\"\${TARGET_BUILD_DIR}/\${FRAMEWORKS_FOLDER_PATH}/InstantSearchCore.framework\\", + "\${TARGET_BUILD_DIR}/\${FRAMEWORKS_FOLDER_PATH}/InstantSearch.framework", + "\${TARGET_BUILD_DIR}/\${FRAMEWORKS_FOLDER_PATH}/InstantSearchClient.framework", + "\${TARGET_BUILD_DIR}/\${FRAMEWORKS_FOLDER_PATH}/InstantSearchCore.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = \\"\\\\\\"\${SRCROOT}/Pods/Target Support Files/Pods-App/Pods-App-frameworks.sh\\\\\\"\\\\n\\"; + shellScript = "\\"\${SRCROOT}/Pods/Target Support Files/Pods-App/Pods-App-frameworks.sh\\"\\n"; showEnvVarsInLog = 0; }; 6ED659C468517EE7AE9D6746 /* [CP] Check Pods Manifest.lock */ = { @@ -1138,16 +1138,16 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj files = ( ); inputPaths = ( - \\"\${PODS_PODFILE_DIR_PATH}/Podfile.lock\\", - \\"\${PODS_ROOT}/Manifest.lock\\", + "\${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "\${PODS_ROOT}/Manifest.lock", ); - name = \\"[CP] Check Pods Manifest.lock\\"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( - \\"$(DERIVED_FILE_DIR)/Pods-App-checkManifestLockResult.txt\\", + "$(DERIVED_FILE_DIR)/Pods-App-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = \\"diff \\\\\\"\${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\\\\" \\\\\\"\${PODS_ROOT}/Manifest.lock\\\\\\" > /dev/null\\\\nif [ $? != 0 ] ; then\\\\n # print error to STDERR\\\\n echo \\\\\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\\\\" >&2\\\\n exit 1\\\\nfi\\\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\\\necho \\\\\\"SUCCESS\\\\\\" > \\\\\\"\${SCRIPT_OUTPUT_FILE_0}\\\\\\"\\\\n\\"; + shellScript = "diff \\"\${PODS_PODFILE_DIR_PATH}/Podfile.lock\\" \\"\${PODS_ROOT}/Manifest.lock\\" > /dev/null\\nif [ $? != 0 ] ; then\\n # print error to STDERR\\n echo \\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\" >&2\\n exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\"SUCCESS\\" > \\"\${SCRIPT_OUTPUT_FILE_0}\\"\\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -1171,7 +1171,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj E258C92B1EE036970076097D /* Base */, ); name = Main.storyboard; - sourceTree = \\"\\"; + sourceTree = ""; }; E258C92F1EE036970076097D /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; @@ -1179,7 +1179,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj E258C9301EE036970076097D /* Base */, ); name = LaunchScreen.storyboard; - sourceTree = \\"\\"; + sourceTree = ""; }; /* End PBXVariantGroup section */ @@ -1190,8 +1190,8 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = \\"gnu++0x\\"; - CLANG_CXX_LIBRARY = \\"libc++\\"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -1206,7 +1206,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - \\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\\" = \\"iPhone Developer\\"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1216,8 +1216,8 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - \\"DEBUG=1\\", - \\"$(inherited)\\", + "DEBUG=1", + "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -1230,7 +1230,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = \\"-Onone\\"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; @@ -1240,8 +1240,8 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = \\"gnu++0x\\"; - CLANG_CXX_LIBRARY = \\"libc++\\"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -1256,9 +1256,9 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - \\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\\" = \\"iPhone Developer\\"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = \\"dwarf-with-dsym\\"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1272,7 +1272,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj IPHONEOS_DEPLOYMENT_TARGET = 10.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = \\"-Owholemodule\\"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -1283,10 +1283,10 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = K3DV6EU9CV; - INFOPLIST_FILE = \\"App/Info.plist\\"; - LD_RUNPATH_SEARCH_PATHS = \\"$(inherited) @executable_path/Frameworks\\"; - PRODUCT_BUNDLE_IDENTIFIER = \\"io.daher.Getting-Started-Programatically\\"; - PRODUCT_NAME = \\"$(TARGET_NAME)\\"; + INFOPLIST_FILE = "App/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "io.daher.Getting-Started-Programatically"; + PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Debug; @@ -1297,10 +1297,10 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = K3DV6EU9CV; - INFOPLIST_FILE = \\"App/Info.plist\\"; - LD_RUNPATH_SEARCH_PATHS = \\"$(inherited) @executable_path/Frameworks\\"; - PRODUCT_BUNDLE_IDENTIFIER = \\"io.daher.Getting-Started-Programatically\\"; - PRODUCT_NAME = \\"$(TARGET_NAME)\\"; + INFOPLIST_FILE = "App/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "io.daher.Getting-Started-Programatically"; + PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; @@ -1308,7 +1308,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - E258C91E1EE036970076097D /* Build configuration list for PBXProject \\"App\\" */ = { + E258C91E1EE036970076097D /* Build configuration list for PBXProject "App" */ = { isa = XCConfigurationList; buildConfigurations = ( E258C9331EE036970076097D /* Debug */, @@ -1317,7 +1317,7 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - E258C9351EE036970076097D /* Build configuration list for PBXNativeTarget \\"App\\" */ = { + E258C9351EE036970076097D /* Build configuration list for PBXNativeTarget "App" */ = { isa = XCConfigurationList; buildConfigurations = ( E258C9361EE036970076097D /* Debug */, @@ -1332,33 +1332,33 @@ exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.pbxproj }" `; -exports[`Templates InstantSearch iOS File content: App.xcodeproj/project.xcworkspace/contents.xcworkspacedata 1`] = ` -" +exports[`Templates > InstantSearch iOS > File content > App.xcodeproj/project.xcworkspace/contents.xcworkspacedata 1`] = ` +" + version = "1.0"> + location = "self:App.xcodeproj"> " `; -exports[`Templates InstantSearch iOS File content: App.xcworkspace/contents.xcworkspacedata 1`] = ` -" +exports[`Templates > InstantSearch iOS > File content > App.xcworkspace/contents.xcworkspacedata 1`] = ` +" + version = "1.0"> + location = "group:App.xcodeproj"> + location = "group:Pods/Pods.xcodeproj"> " `; -exports[`Templates InstantSearch iOS File content: App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist 1`] = ` -" - - +exports[`Templates > InstantSearch iOS > File content > App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist 1`] = ` +" + + IDEDidComputeMac32BitWarning @@ -1366,7 +1366,7 @@ exports[`Templates InstantSearch iOS File content: App.xcworkspace/xcshareddata/ " `; -exports[`Templates InstantSearch iOS File content: App/AppDelegate.swift 1`] = ` +exports[`Templates > InstantSearch iOS > File content > App/AppDelegate.swift 1`] = ` "import UIKit import InstantSearch @@ -1375,15 +1375,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - private let ALGOLIA_APP_ID = \\"appId\\" - private let ALGOLIA_API_KEY = \\"apiKey\\" - private let ALGOLIA_INDEX_NAME = \\"indexName\\" + private let ALGOLIA_APP_ID = "appId" + private let ALGOLIA_API_KEY = "apiKey" + private let ALGOLIA_INDEX_NAME = "indexName" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. InstantSearch.shared.configure(appID: ALGOLIA_APP_ID, apiKey: ALGOLIA_API_KEY, index: ALGOLIA_INDEX_NAME) - InstantSearch.shared.params.attributesToRetrieve = [\\"attribute1\\", \\"attribute2\\"] - InstantSearch.shared.params.attributesToHighlight = [\\"attribute1\\", \\"attribute2\\"] + InstantSearch.shared.params.attributesToRetrieve = ["attribute1", "attribute2"] + InstantSearch.shared.params.attributesToHighlight = ["attribute1", "attribute2"] return true } @@ -1414,125 +1414,125 @@ class AppDelegate: UIResponder, UIApplicationDelegate { }" `; -exports[`Templates InstantSearch iOS File content: App/Assets.xcassets/AppIcon.appiconset/Contents.json 1`] = ` +exports[`Templates > InstantSearch iOS > File content > App/Assets.xcassets/AppIcon.appiconset/Contents.json 1`] = ` "{ - \\"images\\": [ + "images": [ { - \\"idiom\\": \\"iphone\\", - \\"size\\": \\"20x20\\", - \\"scale\\": \\"2x\\" + "idiom": "iphone", + "size": "20x20", + "scale": "2x" }, { - \\"idiom\\": \\"iphone\\", - \\"size\\": \\"20x20\\", - \\"scale\\": \\"3x\\" + "idiom": "iphone", + "size": "20x20", + "scale": "3x" }, { - \\"idiom\\": \\"iphone\\", - \\"size\\": \\"29x29\\", - \\"scale\\": \\"2x\\" + "idiom": "iphone", + "size": "29x29", + "scale": "2x" }, { - \\"idiom\\": \\"iphone\\", - \\"size\\": \\"29x29\\", - \\"scale\\": \\"3x\\" + "idiom": "iphone", + "size": "29x29", + "scale": "3x" }, { - \\"idiom\\": \\"iphone\\", - \\"size\\": \\"40x40\\", - \\"scale\\": \\"2x\\" + "idiom": "iphone", + "size": "40x40", + "scale": "2x" }, { - \\"idiom\\": \\"iphone\\", - \\"size\\": \\"40x40\\", - \\"scale\\": \\"3x\\" + "idiom": "iphone", + "size": "40x40", + "scale": "3x" }, { - \\"idiom\\": \\"iphone\\", - \\"size\\": \\"60x60\\", - \\"scale\\": \\"2x\\" + "idiom": "iphone", + "size": "60x60", + "scale": "2x" }, { - \\"idiom\\": \\"iphone\\", - \\"size\\": \\"60x60\\", - \\"scale\\": \\"3x\\" + "idiom": "iphone", + "size": "60x60", + "scale": "3x" } ], - \\"info\\": { - \\"version\\": 1, - \\"author\\": \\"xcode\\" + "info": { + "version": 1, + "author": "xcode" } }" `; -exports[`Templates InstantSearch iOS File content: App/Base.lproj/LaunchScreen.storyboard 1`] = ` -" - +exports[`Templates > InstantSearch iOS > File content > App/Base.lproj/LaunchScreen.storyboard 1`] = ` +" + - - + + - + - + - - + + - - - - + + + + - + - + " `; -exports[`Templates InstantSearch iOS File content: App/Base.lproj/Main.storyboard 1`] = ` -" - - - +exports[`Templates > InstantSearch iOS > File content > App/Base.lproj/Main.storyboard 1`] = ` +" + + + - - - + + + - + - + - - + + - - - - + + + + - + - + " `; -exports[`Templates InstantSearch iOS File content: App/Info.plist 1`] = ` -" - - +exports[`Templates > InstantSearch iOS > File content > App/Info.plist 1`] = ` +" + + CFBundleDevelopmentRegion en @@ -1570,7 +1570,7 @@ exports[`Templates InstantSearch iOS File content: App/Info.plist 1`] = ` " `; -exports[`Templates InstantSearch iOS File content: App/ViewController.swift 1`] = ` +exports[`Templates > InstantSearch iOS > File content > App/ViewController.swift 1`] = ` "import UIKit import InstantSearch import InstantSearchCore @@ -1595,11 +1595,11 @@ class ViewController: HitsTableViewController { } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath, containing hit: [String : Any]) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: \\"hitCell\\", for: indexPath) + let cell = tableView.dequeueReusableCell(withIdentifier: "hitCell", for: indexPath) cell.textLabel?.highlightedTextColor = .blue cell.textLabel?.highlightedBackgroundColor = .yellow - cell.textLabel?.highlightedText = SearchResults.highlightResult(hit: hit, path: \\"attribute1\\")?.value + cell.textLabel?.highlightedText = SearchResults.highlightResult(hit: hit, path: "attribute1")?.value return cell } @@ -1615,16 +1615,16 @@ class ViewController: HitsTableViewController { stats.translatesAutoresizingMaskIntoConstraints = false tableView.translatesAutoresizingMaskIntoConstraints = false - let views = [\\"searchBar\\": searchBar, \\"stats\\": stats, \\"tableView\\": tableView] + let views = ["searchBar": searchBar, "stats": stats, "tableView": tableView] var constraints = [NSLayoutConstraint]() - constraints += NSLayoutConstraint.constraints(withVisualFormat: \\"V:|-30-[searchBar]-10-[stats]-10-[tableView]-|\\", options: [], metrics: nil, views:views) - constraints += NSLayoutConstraint.constraints(withVisualFormat: \\"H:|-25-[searchBar]-25-|\\", options: [], metrics: nil, views:views) - constraints += NSLayoutConstraint.constraints(withVisualFormat: \\"H:|-25-[stats]-25-|\\", options: [], metrics: nil, views:views) - constraints += NSLayoutConstraint.constraints(withVisualFormat: \\"H:|-[tableView]-|\\", options: [], metrics: nil, views:views) + constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-30-[searchBar]-10-[stats]-10-[tableView]-|", options: [], metrics: nil, views:views) + constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-25-[searchBar]-25-|", options: [], metrics: nil, views:views) + constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-25-[stats]-25-|", options: [], metrics: nil, views:views) + constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-[tableView]-|", options: [], metrics: nil, views:views) NSLayoutConstraint.activate(constraints) // Register tableView identifier - tableView.register(UITableViewCell.self, forCellReuseIdentifier: \\"hitCell\\") + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "hitCell") // Style the stats label stats.textAlignment = .center @@ -1634,7 +1634,7 @@ class ViewController: HitsTableViewController { }" `; -exports[`Templates InstantSearch iOS File content: Podfile 1`] = ` +exports[`Templates > InstantSearch iOS > File content > Podfile 1`] = ` "# Uncomment the next line to define a global platform for your project # platform :ios, '9.0' @@ -1648,8 +1648,8 @@ target 'App' do end" `; -exports[`Templates InstantSearch iOS Folder structure: contains the right files 1`] = ` -Array [ +exports[`Templates > InstantSearch iOS > Folder structure > contains the right files 1`] = ` +[ ".gitignore", "App.xcodeproj/project.pbxproj", "App.xcodeproj/project.xcworkspace/contents.xcworkspacedata", @@ -1665,7 +1665,7 @@ Array [ ] `; -exports[`Templates InstantSearch.js File content: .editorconfig 1`] = ` +exports[`Templates > InstantSearch.js > File content > .editorconfig 1`] = ` "root = true [*] @@ -1677,19 +1677,19 @@ insert_final_newline = true trim_trailing_whitespace = true" `; -exports[`Templates InstantSearch.js File content: .eslintignore 1`] = ` +exports[`Templates > InstantSearch.js > File content > .eslintignore 1`] = ` "/node_modules /dist /.cache" `; -exports[`Templates InstantSearch.js File content: .eslintrc.js 1`] = ` +exports[`Templates > InstantSearch.js > File content > .eslintrc.js 1`] = ` "module.exports = { extends: 'algolia', };" `; -exports[`Templates InstantSearch.js File content: .gitignore 1`] = ` +exports[`Templates > InstantSearch.js > File content > .gitignore 1`] = ` "# See https://help.github.com/ignore-files/ for more about ignoring files. # dependencies @@ -1714,15 +1714,15 @@ yarn-debug.log* yarn-error.log*" `; -exports[`Templates InstantSearch.js File content: .prettierrc 1`] = ` +exports[`Templates > InstantSearch.js > File content > .prettierrc 1`] = ` "{ - \\"singleQuote\\": true, - \\"proseWrap\\": \\"never\\", - \\"trailingComma\\": \\"es5\\" + "singleQuote": true, + "proseWrap": "never", + "trailingComma": "es5" }" `; -exports[`Templates InstantSearch.js File content: README.md 1`] = ` +exports[`Templates > InstantSearch.js > File content > README.md 1`] = ` "# instantsearch.js-app _This project was generated with [create-instantsearch-app](https://github.com/algolia/instantsearch/tree/master/packages/create-instantsearch-app) by [Algolia](https://algolia.com)._ @@ -1746,81 +1746,81 @@ yarn start Open http://localhost:3000 to see your app." `; -exports[`Templates InstantSearch.js File content: index.html 1`] = ` +exports[`Templates > InstantSearch.js > File content > index.html 1`] = ` " - + - - - + + + - + - - - + + + instantsearch.js-app -
-

- instantsearch.js-app +
+

+ instantsearch.js-app

-

+

using - + InstantSearch.js

-
-
-
-
+
+
+
+
-
-
-
-
+
+ +
+
- - - + + + " `; -exports[`Templates InstantSearch.js File content: package.json 1`] = ` +exports[`Templates > InstantSearch.js > File content > package.json 1`] = ` "{ - \\"name\\": \\"instantsearch.js-app\\", - \\"version\\": \\"1.0.0\\", - \\"private\\": true, - \\"scripts\\": { - \\"start\\": \\"parcel index.html --port 3000\\", - \\"build\\": \\"parcel build index.html\\", - \\"lint\\": \\"eslint . && prettier --check .\\", - \\"lint:fix\\": \\"eslint . --fix && prettier --write .\\" + "name": "instantsearch.js-app", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "parcel index.html --port 3000", + "build": "parcel build index.html", + "lint": "eslint . && prettier --check .", + "lint:fix": "eslint . --fix && prettier --write ." }, - \\"partialDependencies\\": { - \\"instantsearch.js\\": \\"3.0.0\\" + "partialDependencies": { + "instantsearch.js": "3.0.0" } }" `; -exports[`Templates InstantSearch.js File content: src/app.css 1`] = ` +exports[`Templates > InstantSearch.js > File content > src/app.css 1`] = ` ".header { display: flex; align-items: center; @@ -1892,7 +1892,7 @@ exports[`Templates InstantSearch.js File content: src/app.css 1`] = ` }" `; -exports[`Templates InstantSearch.js File content: src/app.js 1`] = ` +exports[`Templates > InstantSearch.js > File content > src/app.js 1`] = ` "const { algoliasearch, instantsearch } = window; const searchClient = algoliasearch('appId', 'apiKey'); @@ -1961,7 +1961,7 @@ search.addWidgets([ search.start();" `; -exports[`Templates InstantSearch.js File content: src/global.d.ts 1`] = ` +exports[`Templates > InstantSearch.js > File content > src/global.d.ts 1`] = ` "import algoliasearch from 'algoliasearch/lite'; import instantsearch from 'instantsearch.js/dist/instantsearch.production.min'; @@ -1973,7 +1973,7 @@ declare global { }" `; -exports[`Templates InstantSearch.js File content: src/index.css 1`] = ` +exports[`Templates > InstantSearch.js > File content > src/index.css 1`] = ` "body, h1 { margin: 0; @@ -1986,29 +1986,29 @@ body { }" `; -exports[`Templates InstantSearch.js File content: tsconfig.json 1`] = ` +exports[`Templates > InstantSearch.js > File content > tsconfig.json 1`] = ` "{ - \\"compilerOptions\\": { - \\"module\\": \\"commonjs\\", - \\"esModuleInterop\\": true, - \\"sourceMap\\": true, - \\"allowJs\\": true, - \\"lib\\": [ - \\"es6\\", - \\"dom\\" + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "sourceMap": true, + "allowJs": true, + "lib": [ + "es6", + "dom" ], - \\"rootDir\\": \\"src\\", - \\"moduleResolution\\": \\"node\\" + "rootDir": "src", + "moduleResolution": "node" }, - \\"include\\": [ - \\"src\\", - \\"src/global.d.ts\\" + "include": [ + "src", + "src/global.d.ts" ] }" `; -exports[`Templates InstantSearch.js Folder structure: contains the right files 1`] = ` -Array [ +exports[`Templates > InstantSearch.js > Folder structure > contains the right files 1`] = ` +[ ".editorconfig", ".eslintignore", ".eslintrc.js", @@ -2026,7 +2026,7 @@ Array [ ] `; -exports[`Templates InstantSearch.js widget File content: .eslintignore 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > .eslintignore 1`] = ` "# Vendors node_modules @@ -2034,7 +2034,7 @@ node_modules dist" `; -exports[`Templates InstantSearch.js widget File content: .eslintrc.cjs 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > .eslintrc.cjs 1`] = ` "module.exports = { extends: ['algolia', 'algolia/jest', 'algolia/typescript'], rules: { @@ -2058,7 +2058,7 @@ exports[`Templates InstantSearch.js widget File content: .eslintrc.cjs 1`] = ` };" `; -exports[`Templates InstantSearch.js widget File content: .gitignore 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > .gitignore 1`] = ` "node_modules/ npm-debug.log yarn-debug.log @@ -2066,15 +2066,15 @@ yarn-error.log dist/" `; -exports[`Templates InstantSearch.js widget File content: .prettierrc 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > .prettierrc 1`] = ` "{ - \\"singleQuote\\": true, - \\"proseWrap\\": \\"never\\", - \\"trailingComma\\": \\"es5\\" + "singleQuote": true, + "proseWrap": "never", + "trailingComma": "es5" }" `; -exports[`Templates InstantSearch.js widget File content: CONTRIBUTING.md 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > CONTRIBUTING.md 1`] = ` "# Contribution Guide ## Test @@ -2122,13 +2122,13 @@ If you want to publish it as a public scoped package, run \`npm publish --access [To know more about \`standard-version\`, read this →](https://github.com/conventional-changelog/standard-version#cli-usage)" `; -exports[`Templates InstantSearch.js widget File content: LICENSE.md 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > LICENSE.md 1`] = ` "The MIT License (MIT) Copyright (c) 2020-present algolia. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the \\"Software\\"), to deal +of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is @@ -2137,7 +2137,7 @@ furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED \\"AS IS\\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER @@ -2146,7 +2146,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." `; -exports[`Templates InstantSearch.js widget File content: README.md 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > README.md 1`] = ` "# date-picker @@ -2321,7 +2321,7 @@ Please read [our contribution process](./CONTRIBUTING.md) to learn more. _This project was generated with [create-instantsearch-app](https://github.com/algolia/instantsearch/tree/master/packages/create-instantsearch-app) by [Algolia](https://algolia.com)._" `; -exports[`Templates InstantSearch.js widget File content: babel.config.cjs 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > babel.config.cjs 1`] = ` "/* eslint-disable import/no-commonjs */ module.exports = (api) => { const isCJS = process.env.BABEL_ENV === 'cjs'; @@ -2382,97 +2382,97 @@ module.exports = (api) => { };" `; -exports[`Templates InstantSearch.js widget File content: config/api-extractor.json 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > config/api-extractor.json 1`] = ` "/** * Config file for API Extractor. For more info, please visit: https://api-extractor.com */ { - \\"$schema\\": \\"https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json\\", + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", /** * Optionally specifies another JSON config file that this file extends from. This provides a way for * standard settings to be shared across multiple projects. * - * If the path starts with \\"./\\" or \\"../\\", the path is resolved relative to the folder of the file that contains - * the \\"extends\\" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be + * If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains + * the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be * resolved using NodeJS require(). * * SUPPORTED TOKENS: none - * DEFAULT VALUE: \\"\\" + * DEFAULT VALUE: "" */ - // \\"extends\\": \\"./shared/api-extractor-base.json\\" + // "extends": "./shared/api-extractor-base.json" /** - * Determines the \\"\\" token that can be used with other config file settings. The project folder + * Determines the "" token that can be used with other config file settings. The project folder * typically contains the tsconfig.json and package.json config files, but the path is user-defined. * * The path is resolved relative to the folder of the config file that contains the setting. * - * The default value for \\"projectFolder\\" is the token \\"\\", which means the folder is determined by traversing + * The default value for "projectFolder" is the token "", which means the folder is determined by traversing * parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder * that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error * will be reported. * * SUPPORTED TOKENS: - * DEFAULT VALUE: \\"\\" + * DEFAULT VALUE: "" */ - \\"projectFolder\\": \\"..\\", + "projectFolder": "..", /** * (REQUIRED) Specifies the .d.ts file to be used as the starting point for analysis. API Extractor * analyzes the symbols exported by this module. * - * The file extension must be \\".d.ts\\" and not \\".ts\\". + * The file extension must be ".d.ts" and not ".ts". * * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as \\"\\". + * prepend a folder token such as "". * * SUPPORTED TOKENS: , , */ - \\"mainEntryPointFilePath\\": \\"/dist/_types/index.d.ts\\", + "mainEntryPointFilePath": "/dist/_types/index.d.ts", /** * A list of NPM package names whose exports should be treated as part of this package. * - * For example, suppose that Webpack is used to generate a distributed bundle for the project \\"library1\\", - * and another NPM package \\"library2\\" is embedded in this bundle. Some types from library2 may become part + * For example, suppose that Webpack is used to generate a distributed bundle for the project "library1", + * and another NPM package "library2" is embedded in this bundle. Some types from library2 may become part * of the exported API for library1, but by default API Extractor would generate a .d.ts rollup that explicitly * imports library2. To avoid this, we can specify: * - * \\"bundledPackages\\": [ \\"library2\\" ], + * "bundledPackages": [ "library2" ], * * This would direct API Extractor to embed those types directly in the .d.ts rollup, as if they had been * local files for library1. */ - \\"bundledPackages\\": [], + "bundledPackages": [], /** * Determines how the TypeScript compiler engine will be invoked by API Extractor. */ - \\"compiler\\": { + "compiler": { /** * Specifies the path to the tsconfig.json file to be used by API Extractor when analyzing the project. * * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as \\"\\". + * prepend a folder token such as "". * - * Note: This setting will be ignored if \\"overrideTsconfig\\" is used. + * Note: This setting will be ignored if "overrideTsconfig" is used. * * SUPPORTED TOKENS: , , - * DEFAULT VALUE: \\"/tsconfig.json\\" + * DEFAULT VALUE: "/tsconfig.json" */ - \\"tsconfigFilePath\\": \\"/tsconfig.declaration.json\\" + "tsconfigFilePath": "/tsconfig.declaration.json" /** * Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk. * The object must conform to the TypeScript tsconfig schema: * * http://json.schemastore.org/tsconfig * - * If omitted, then the tsconfig.json file will be read from the \\"projectFolder\\". + * If omitted, then the tsconfig.json file will be read from the "projectFolder". * * DEFAULT VALUE: no overrideTsconfig section */ - // \\"overrideTsconfig\\": { + // "overrideTsconfig": { // . . . // } /** @@ -2483,89 +2483,89 @@ exports[`Templates InstantSearch.js widget File content: config/api-extractor.js * * DEFAULT VALUE: false */ - // \\"skipLibCheck\\": true, + // "skipLibCheck": true, }, /** * Configures how the API report file (*.api.md) will be generated. */ - \\"apiReport\\": { + "apiReport": { /** * (REQUIRED) Whether to generate an API report. */ - \\"enabled\\": false + "enabled": false /** - * The filename for the API report files. It will be combined with \\"reportFolder\\" or \\"reportTempFolder\\" to produce + * The filename for the API report files. It will be combined with "reportFolder" or "reportTempFolder" to produce * a full file path. * - * The file extension should be \\".api.md\\", and the string should not contain a path separator such as \\"\\\\\\" or \\"/\\". + * The file extension should be ".api.md", and the string should not contain a path separator such as "\\" or "/". * * SUPPORTED TOKENS: , - * DEFAULT VALUE: \\".api.md\\" + * DEFAULT VALUE: ".api.md" */ - // \\"reportFileName\\": \\".api.md\\", + // "reportFileName": ".api.md", /** * Specifies the folder where the API report file is written. The file name portion is determined by - * the \\"reportFileName\\" setting. + * the "reportFileName" setting. * * The API report file is normally tracked by Git. Changes to it can be used to trigger a branch policy, * e.g. for an API review. * * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as \\"\\". + * prepend a folder token such as "". * * SUPPORTED TOKENS: , , - * DEFAULT VALUE: \\"/etc/\\" + * DEFAULT VALUE: "/etc/" */ - // \\"reportFolder\\": \\"/etc/\\", + // "reportFolder": "/etc/", /** * Specifies the folder where the temporary report file is written. The file name portion is determined by - * the \\"reportFileName\\" setting. + * the "reportFileName" setting. * - * After the temporary file is written to disk, it is compared with the file in the \\"reportFolder\\". + * After the temporary file is written to disk, it is compared with the file in the "reportFolder". * If they are different, a production build will fail. * * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as \\"\\". + * prepend a folder token such as "". * * SUPPORTED TOKENS: , , - * DEFAULT VALUE: \\"/temp/\\" + * DEFAULT VALUE: "/temp/" */ - // \\"reportTempFolder\\": \\"/temp/\\" + // "reportTempFolder": "/temp/" }, /** * Configures how the doc model file (*.api.json) will be generated. */ - \\"docModel\\": { + "docModel": { /** * (REQUIRED) Whether to generate a doc model file. */ - \\"enabled\\": false + "enabled": false /** - * The output path for the doc model file. The file extension should be \\".api.json\\". + * The output path for the doc model file. The file extension should be ".api.json". * * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as \\"\\". + * prepend a folder token such as "". * * SUPPORTED TOKENS: , , - * DEFAULT VALUE: \\"/temp/.api.json\\" + * DEFAULT VALUE: "/temp/.api.json" */ - // \\"apiJsonFilePath\\": \\"/temp/.api.json\\" + // "apiJsonFilePath": "/temp/.api.json" }, /** * Configures how the .d.ts rollup file will be generated. */ - \\"dtsRollup\\": { + "dtsRollup": { /** * (REQUIRED) Whether to generate the .d.ts rollup file. */ - \\"enabled\\": true, + "enabled": true, /** * Specifies the output path for a .d.ts rollup file to be generated without any trimming. @@ -2574,130 +2574,130 @@ exports[`Templates InstantSearch.js widget File content: config/api-extractor.js * If the path is an empty string, then this file will not be written. * * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as \\"\\". + * prepend a folder token such as "". * * SUPPORTED TOKENS: , , - * DEFAULT VALUE: \\"/dist/.d.ts\\" + * DEFAULT VALUE: "/dist/.d.ts" */ - \\"untrimmedFilePath\\": \\"/dist/index.es.d.ts\\" + "untrimmedFilePath": "/dist/index.es.d.ts" /** - * Specifies the output path for a .d.ts rollup file to be generated with trimming for a \\"beta\\" release. - * This file will include only declarations that are marked as \\"@public\\" or \\"@beta\\". + * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "beta" release. + * This file will include only declarations that are marked as "@public" or "@beta". * * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as \\"\\". + * prepend a folder token such as "". * * SUPPORTED TOKENS: , , - * DEFAULT VALUE: \\"\\" + * DEFAULT VALUE: "" */ - // \\"betaTrimmedFilePath\\": \\"/dist/-beta.d.ts\\", + // "betaTrimmedFilePath": "/dist/-beta.d.ts", /** - * Specifies the output path for a .d.ts rollup file to be generated with trimming for a \\"public\\" release. - * This file will include only declarations that are marked as \\"@public\\". + * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "public" release. + * This file will include only declarations that are marked as "@public". * * If the path is an empty string, then this file will not be written. * * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as \\"\\". + * prepend a folder token such as "". * * SUPPORTED TOKENS: , , - * DEFAULT VALUE: \\"\\" + * DEFAULT VALUE: "" */ - // \\"publicTrimmedFilePath\\": \\"/dist/-public.d.ts\\", + // "publicTrimmedFilePath": "/dist/-public.d.ts", /** * When a declaration is trimmed, by default it will be replaced by a code comment such as - * \\"Excluded from this release type: exampleMember\\". Set \\"omitTrimmingComments\\" to true to remove the + * "Excluded from this release type: exampleMember". Set "omitTrimmingComments" to true to remove the * declaration completely. * * DEFAULT VALUE: false */ - // \\"omitTrimmingComments\\": true + // "omitTrimmingComments": true }, /** * Configures how the tsdoc-metadata.json file will be generated. */ - \\"tsdocMetadata\\": { + "tsdocMetadata": { /** * Whether to generate the tsdoc-metadata.json file. * * DEFAULT VALUE: true */ - \\"enabled\\": false + "enabled": false /** * Specifies where the TSDoc metadata file should be written. * * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as \\"\\". + * prepend a folder token such as "". * - * The default value is \\"\\", which causes the path to be automatically inferred from the \\"tsdocMetadata\\", - * \\"typings\\" or \\"main\\" fields of the project's package.json. If none of these fields are set, the lookup - * falls back to \\"tsdoc-metadata.json\\" in the package folder. + * The default value is "", which causes the path to be automatically inferred from the "tsdocMetadata", + * "typings" or "main" fields of the project's package.json. If none of these fields are set, the lookup + * falls back to "tsdoc-metadata.json" in the package folder. * * SUPPORTED TOKENS: , , - * DEFAULT VALUE: \\"\\" + * DEFAULT VALUE: "" */ - // \\"tsdocMetadataFilePath\\": \\"/dist/tsdoc-metadata.json\\" + // "tsdocMetadataFilePath": "/dist/tsdoc-metadata.json" }, /** * Specifies what type of newlines API Extractor should use when writing output files. By default, the output files - * will be written with Windows-style newlines. To use POSIX-style newlines, specify \\"lf\\" instead. - * To use the OS's default newline kind, specify \\"os\\". + * will be written with Windows-style newlines. To use POSIX-style newlines, specify "lf" instead. + * To use the OS's default newline kind, specify "os". * - * DEFAULT VALUE: \\"crlf\\" + * DEFAULT VALUE: "crlf" */ - // \\"newlineKind\\": \\"crlf\\", + // "newlineKind": "crlf", /** * Configures how API Extractor reports error and warning messages produced during analysis. * * There are three sources of messages: compiler messages, API Extractor messages, and TSDoc messages. */ - \\"messages\\": { + "messages": { /** * Configures handling of diagnostic messages reported by the TypeScript compiler engine while analyzing * the input .d.ts files. * - * TypeScript message identifiers start with \\"TS\\" followed by an integer. For example: \\"TS2551\\" + * TypeScript message identifiers start with "TS" followed by an integer. For example: "TS2551" * - * DEFAULT VALUE: A single \\"default\\" entry with logLevel=warning. + * DEFAULT VALUE: A single "default" entry with logLevel=warning. */ - \\"compilerMessageReporting\\": { + "compilerMessageReporting": { /** * Configures the default routing for messages that don't match an explicit rule in this table. */ - \\"default\\": { + "default": { /** * Specifies whether the message should be written to the the tool's output log. Note that - * the \\"addToApiReportFile\\" property may supersede this option. + * the "addToApiReportFile" property may supersede this option. * - * Possible values: \\"error\\", \\"warning\\", \\"none\\" + * Possible values: "error", "warning", "none" * * Errors cause the build to fail and return a nonzero exit code. Warnings cause a production build fail - * and return a nonzero exit code. For a non-production build (e.g. when \\"api-extractor run\\" includes - * the \\"--local\\" option), the warning is displayed but the build will not fail. + * and return a nonzero exit code. For a non-production build (e.g. when "api-extractor run" includes + * the "--local" option), the warning is displayed but the build will not fail. * - * DEFAULT VALUE: \\"warning\\" + * DEFAULT VALUE: "warning" */ - \\"logLevel\\": \\"warning\\" + "logLevel": "warning" /** * When addToApiReportFile is true: If API Extractor is configured to write an API report file (.api.md), * then the message will be written inside that file; otherwise, the message is instead logged according to - * the \\"logLevel\\" option. + * the "logLevel" option. * * DEFAULT VALUE: false */ - // \\"addToApiReportFile\\": false + // "addToApiReportFile": false } - // \\"TS2551\\": { - // \\"logLevel\\": \\"warning\\", - // \\"addToApiReportFile\\": true + // "TS2551": { + // "logLevel": "warning", + // "addToApiReportFile": true // }, // // . . . @@ -2706,23 +2706,23 @@ exports[`Templates InstantSearch.js widget File content: config/api-extractor.js /** * Configures handling of messages reported by API Extractor during its analysis. * - * API Extractor message identifiers start with \\"ae-\\". For example: \\"ae-extra-release-tag\\" + * API Extractor message identifiers start with "ae-". For example: "ae-extra-release-tag" * * DEFAULT VALUE: See api-extractor-defaults.json for the complete table of extractorMessageReporting mappings */ - \\"extractorMessageReporting\\": { - \\"default\\": { - \\"logLevel\\": \\"warning\\" - // \\"addToApiReportFile\\": false + "extractorMessageReporting": { + "default": { + "logLevel": "warning" + // "addToApiReportFile": false }, - \\"ae-missing-release-tag\\": { - \\"logLevel\\": \\"none\\" + "ae-missing-release-tag": { + "logLevel": "none" } - // \\"ae-extra-release-tag\\": { - // \\"logLevel\\": \\"warning\\", - // \\"addToApiReportFile\\": true + // "ae-extra-release-tag": { + // "logLevel": "warning", + // "addToApiReportFile": true // }, // // . . . @@ -2731,19 +2731,19 @@ exports[`Templates InstantSearch.js widget File content: config/api-extractor.js /** * Configures handling of messages reported by the TSDoc parser when analyzing code comments. * - * TSDoc message identifiers start with \\"tsdoc-\\". For example: \\"tsdoc-link-tag-unescaped-text\\" + * TSDoc message identifiers start with "tsdoc-". For example: "tsdoc-link-tag-unescaped-text" * - * DEFAULT VALUE: A single \\"default\\" entry with logLevel=warning. + * DEFAULT VALUE: A single "default" entry with logLevel=warning. */ - \\"tsdocMessageReporting\\": { - \\"default\\": { - \\"logLevel\\": \\"warning\\" - // \\"addToApiReportFile\\": false + "tsdocMessageReporting": { + "default": { + "logLevel": "warning" + // "addToApiReportFile": false } - // \\"tsdoc-link-tag-unescaped-text\\": { - // \\"logLevel\\": \\"warning\\", - // \\"addToApiReportFile\\": true + // "tsdoc-link-tag-unescaped-text": { + // "logLevel": "warning", + // "addToApiReportFile": true // }, // // . . . @@ -2752,7 +2752,7 @@ exports[`Templates InstantSearch.js widget File content: config/api-extractor.js }" `; -exports[`Templates InstantSearch.js widget File content: example/index.css 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > example/index.css 1`] = ` "body { font-family: sans-serif; } @@ -2762,30 +2762,30 @@ exports[`Templates InstantSearch.js widget File content: example/index.css 1`] = }" `; -exports[`Templates InstantSearch.js widget File content: example/index.html 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > example/index.html 1`] = ` " - + - - - + + + - + date-picker example -
-
-
- + +
+
+ " `; -exports[`Templates InstantSearch.js widget File content: example/index.ts 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > example/index.ts 1`] = ` "import algoliasearch from 'algoliasearch/lite'; import instantsearch from 'instantsearch.js/es'; import { configure, hits, searchBox } from 'instantsearch.js/es/widgets'; @@ -2823,57 +2823,57 @@ search.addWidgets([ search.start();" `; -exports[`Templates InstantSearch.js widget File content: package.json 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > package.json 1`] = ` "{ - \\"name\\": \\"@algolia/instantsearch-widget-date-picker\\", - \\"version\\": \\"1.0.0\\", - \\"description\\": \\"\\", - \\"keywords\\": [ - \\"instantsearch-widget\\", - \\"instantsearch\\", - \\"instantsearch-widget-date-picker\\", - \\"widget\\", - \\"connector\\", - \\"algolia\\" + "name": "@algolia/instantsearch-widget-date-picker", + "version": "1.0.0", + "description": "", + "keywords": [ + "instantsearch-widget", + "instantsearch", + "instantsearch-widget-date-picker", + "widget", + "connector", + "algolia" ], - \\"license\\": \\"MIT\\", - \\"main\\": \\"./dist/index.cjs.js\\", - \\"module\\": \\"./dist/index.es.js\\", - \\"exports\\": { - \\"import\\": \\"./dist/index.es.js\\", - \\"require\\": \\"./dist/index.cjs.js\\" + "license": "MIT", + "main": "./dist/index.cjs.js", + "module": "./dist/index.es.js", + "exports": { + "import": "./dist/index.es.js", + "require": "./dist/index.cjs.js" }, - \\"jsdelivr\\": \\"./dist/index.umd.js\\", - \\"unpkg\\": \\"./dist/index.umd.js\\", - \\"types\\": \\"./dist/index.es.d.ts\\", - \\"type\\": \\"module\\", - \\"scripts\\": { - \\"start\\": \\"vite serve example\\", - \\"build\\": \\"vite build && rm -rf dist/_types\\", - \\"test\\": \\"npm run lint && npm run test:types && npm run test:unit\\", - \\"test:unit\\": \\"jest\\", - \\"test:types\\": \\"tsc\\", - \\"lint\\": \\"eslint --ext .js,.ts .\\", - \\"release\\": \\"standard-version\\" + "jsdelivr": "./dist/index.umd.js", + "unpkg": "./dist/index.umd.js", + "types": "./dist/index.es.d.ts", + "type": "module", + "scripts": { + "start": "vite serve example", + "build": "vite build && rm -rf dist/_types", + "test": "npm run lint && npm run test:types && npm run test:unit", + "test:unit": "jest", + "test:types": "tsc", + "lint": "eslint --ext .js,.ts .", + "release": "standard-version" }, - \\"files\\": [ - \\"dist\\" + "files": [ + "dist" ], - \\"peerDependencies\\": { - \\"instantsearch.js\\": \\"^4.27.1\\" + "peerDependencies": { + "instantsearch.js": "^4.27.1" }, - \\"browserslist\\": [ - \\"last 2 chrome versions\\", - \\"last 2 firefox versions\\", - \\"last 2 edge versions\\", - \\"last 2 safari versions\\", - \\"IE 11\\" + "browserslist": [ + "last 2 chrome versions", + "last 2 firefox versions", + "last 2 edge versions", + "last 2 safari versions", + "IE 11" ], - \\"partialDependencies\\": {} + "partialDependencies": {} }" `; -exports[`Templates InstantSearch.js widget File content: src/connector.ts 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > src/connector.ts 1`] = ` "import type { DatePickerConnector } from './types'; /* @@ -2997,14 +2997,14 @@ export const connectDatePicker: DatePickerConnector = };" `; -exports[`Templates InstantSearch.js widget File content: src/index.ts 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > src/index.ts 1`] = ` "export * from './widget'; export * from './connector'; export * from './renderer'; export * from './types';" `; -exports[`Templates InstantSearch.js widget File content: src/renderer.ts 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > src/renderer.ts 1`] = ` "import type { DatePickerRendererCreator } from './types'; /* @@ -3062,7 +3062,7 @@ export const createDatePickerRenderer: DatePickerRendererCreator = ({ };" `; -exports[`Templates InstantSearch.js widget File content: src/types.ts 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > src/types.ts 1`] = ` "import type { Renderer, Connector, WidgetFactory } from 'instantsearch.js/es'; /* @@ -3134,7 +3134,7 @@ export type DatePickerWidgetCreator = WidgetFactory< >;" `; -exports[`Templates InstantSearch.js widget File content: src/widget.ts 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > src/widget.ts 1`] = ` "import { connectDatePicker } from './connector'; import { createDatePickerRenderer } from './renderer'; import type { @@ -3170,37 +3170,37 @@ export const datePicker: DatePickerWidgetCreator = function DatePicker( };" `; -exports[`Templates InstantSearch.js widget File content: tsconfig.declaration.json 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > tsconfig.declaration.json 1`] = ` "{ - \\"extends\\": \\"./tsconfig\\", - \\"compilerOptions\\": { - \\"outDir\\": \\"dist/_types\\", - \\"stripInternal\\": true, - \\"noEmit\\": false, - \\"declaration\\": true, - \\"emitDeclarationOnly\\": true, - \\"declarationMap\\": true + "extends": "./tsconfig", + "compilerOptions": { + "outDir": "dist/_types", + "stripInternal": true, + "noEmit": false, + "declaration": true, + "emitDeclarationOnly": true, + "declarationMap": true }, - \\"include\\": [\\"src\\"], - \\"exclude\\": [\\"**/__tests__\\",\\"**/index.cjs.ts\\"] + "include": ["src"], + "exclude": ["**/__tests__","**/index.cjs.ts"] }" `; -exports[`Templates InstantSearch.js widget File content: tsconfig.json 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > tsconfig.json 1`] = ` "{ - \\"compilerOptions\\": { - \\"target\\": \\"ESNext\\", - \\"moduleResolution\\": \\"node\\", - \\"noEmit\\": true, - \\"strict\\": true, - \\"skipLibCheck\\": true, - \\"allowSyntheticDefaultImports\\": true + "compilerOptions": { + "target": "ESNext", + "moduleResolution": "node", + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true }, - \\"exclude\\": [\\"dist\\"] + "exclude": ["dist"] }" `; -exports[`Templates InstantSearch.js widget File content: vite.config.js 1`] = ` +exports[`Templates > InstantSearch.js widget > File content > vite.config.js 1`] = ` "import { fileURLToPath } from 'url'; import typescript from '@rollup/plugin-typescript'; @@ -3234,8 +3234,8 @@ export default vite.defineConfig({ });" `; -exports[`Templates InstantSearch.js widget Folder structure: contains the right files 1`] = ` -Array [ +exports[`Templates > InstantSearch.js widget > Folder structure > contains the right files 1`] = ` +[ ".eslintignore", ".eslintrc.cjs", ".gitignore", @@ -3260,7 +3260,7 @@ Array [ ] `; -exports[`Templates JavaScript Client File content: .editorconfig 1`] = ` +exports[`Templates > JavaScript Client > File content > .editorconfig 1`] = ` "root = true [*] @@ -3272,19 +3272,19 @@ insert_final_newline = true trim_trailing_whitespace = true" `; -exports[`Templates JavaScript Client File content: .eslintignore 1`] = ` +exports[`Templates > JavaScript Client > File content > .eslintignore 1`] = ` "/node_modules /dist /.cache" `; -exports[`Templates JavaScript Client File content: .eslintrc.js 1`] = ` +exports[`Templates > JavaScript Client > File content > .eslintrc.js 1`] = ` "module.exports = { extends: 'algolia', };" `; -exports[`Templates JavaScript Client File content: .gitignore 1`] = ` +exports[`Templates > JavaScript Client > File content > .gitignore 1`] = ` "# See https://help.github.com/ignore-files/ for more about ignoring files. # dependencies @@ -3309,15 +3309,15 @@ yarn-debug.log* yarn-error.log*" `; -exports[`Templates JavaScript Client File content: .prettierrc 1`] = ` +exports[`Templates > JavaScript Client > File content > .prettierrc 1`] = ` "{ - \\"singleQuote\\": true, - \\"proseWrap\\": \\"never\\", - \\"trailingComma\\": \\"es5\\" + "singleQuote": true, + "proseWrap": "never", + "trailingComma": "es5" }" `; -exports[`Templates JavaScript Client File content: README.md 1`] = ` +exports[`Templates > JavaScript Client > File content > README.md 1`] = ` "# javascript-client-app _This project was generated with [create-instantsearch-app](https://github.com/algolia/instantsearch/tree/master/packages/create-instantsearch-app) by [Algolia](https://algolia.com)._ @@ -3341,92 +3341,92 @@ yarn start Open http://localhost:3000 to see your app." `; -exports[`Templates JavaScript Client File content: index.html 1`] = ` +exports[`Templates > JavaScript Client > File content > index.html 1`] = ` " - + - - - + + + - - + + - - + + javascript-client-app -
-

- javascript-client-app +
+

+ javascript-client-app

-

using the - Algolia Search API Client for JavaScript +

using the + Algolia Search API Client for JavaScript

-
-
-
+
+
+
-
-
-
- +
+ -
+
- + " `; -exports[`Templates JavaScript Client File content: manifest.webmanifest 1`] = ` +exports[`Templates > JavaScript Client > File content > manifest.webmanifest 1`] = ` "{ - \\"short_name\\": \\"javascript-client-app\\", - \\"name\\": \\"javascript-client-app Sample\\", - \\"icons\\": [ + "short_name": "javascript-client-app", + "name": "javascript-client-app Sample", + "icons": [ { - \\"src\\": \\"favicon.png\\", - \\"sizes\\": \\"64x64 32x32 24x24 16x16\\", - \\"type\\": \\"image/x-icon\\" + "src": "favicon.png", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" } ], - \\"start_url\\": \\"./index.html\\", - \\"display\\": \\"standalone\\", - \\"theme_color\\": \\"#000000\\", - \\"background_color\\": \\"#ffffff\\" + "start_url": "./index.html", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" }" `; -exports[`Templates JavaScript Client File content: package.json 1`] = ` +exports[`Templates > JavaScript Client > File content > package.json 1`] = ` "{ - \\"name\\": \\"javascript-client-app\\", - \\"version\\": \\"1.0.0\\", - \\"private\\": true, - \\"main\\": \\"src/app.js\\", - \\"scripts\\": { - \\"start\\": \\"parcel index.html --port 3000\\", - \\"build\\": \\"parcel build index.html\\", - \\"lint\\": \\"eslint .\\", - \\"lint:fix\\": \\"npm run lint -- --fix\\" + "name": "javascript-client-app", + "version": "1.0.0", + "private": true, + "main": "src/app.js", + "scripts": { + "start": "parcel index.html --port 3000", + "build": "parcel build index.html", + "lint": "eslint .", + "lint:fix": "npm run lint -- --fix" }, - \\"partialDependencies\\": { - \\"algoliasearch\\": \\"2.1.0\\" + "partialDependencies": { + "algoliasearch": "2.1.0" } }" `; -exports[`Templates JavaScript Client File content: src/app.css 1`] = ` +exports[`Templates > JavaScript Client > File content > src/app.css 1`] = ` "em { background: cyan; font-style: normal; @@ -3513,7 +3513,7 @@ exports[`Templates JavaScript Client File content: src/app.css 1`] = ` }" `; -exports[`Templates JavaScript Client File content: src/app.js 1`] = ` +exports[`Templates > JavaScript Client > File content > src/app.js 1`] = ` "import algoliasearch from 'algoliasearch'; const client = algoliasearch('appId', 'apiKey'); @@ -3526,13 +3526,13 @@ function renderHits(query) { index.search(query).then((result) => { // Please sanitize user-provided data when using \`innerHTML\` to avoid XSS $hits.innerHTML = \` -
    +
      \${result.hits .map( (hit) => - \`
    1. + \`
    2. - \\"\${hit.attribute1}\\" + \${hit.attribute1}

      \${hit._highlightResult.attribute1.value}

      \${hit._highlightResult.attribute2.value}

      @@ -3554,7 +3554,7 @@ $searchBox.addEventListener('input', (event) => { renderHits('');" `; -exports[`Templates JavaScript Client File content: src/index.css 1`] = ` +exports[`Templates > JavaScript Client > File content > src/index.css 1`] = ` "body, h1 { margin: 0; @@ -3567,8 +3567,8 @@ body { }" `; -exports[`Templates JavaScript Client Folder structure: contains the right files 1`] = ` -Array [ +exports[`Templates > JavaScript Client > Folder structure > contains the right files 1`] = ` +[ ".editorconfig", ".eslintignore", ".eslintrc.js", @@ -3585,7 +3585,7 @@ Array [ ] `; -exports[`Templates JavaScript Helper File content: .editorconfig 1`] = ` +exports[`Templates > JavaScript Helper > File content > .editorconfig 1`] = ` "root = true [*] @@ -3597,19 +3597,19 @@ insert_final_newline = true trim_trailing_whitespace = true" `; -exports[`Templates JavaScript Helper File content: .eslintignore 1`] = ` +exports[`Templates > JavaScript Helper > File content > .eslintignore 1`] = ` "/node_modules /dist /.cache" `; -exports[`Templates JavaScript Helper File content: .eslintrc.js 1`] = ` +exports[`Templates > JavaScript Helper > File content > .eslintrc.js 1`] = ` "module.exports = { extends: 'algolia', };" `; -exports[`Templates JavaScript Helper File content: .gitignore 1`] = ` +exports[`Templates > JavaScript Helper > File content > .gitignore 1`] = ` "# See https://help.github.com/ignore-files/ for more about ignoring files. # dependencies @@ -3634,15 +3634,15 @@ yarn-debug.log* yarn-error.log*" `; -exports[`Templates JavaScript Helper File content: .prettierrc 1`] = ` +exports[`Templates > JavaScript Helper > File content > .prettierrc 1`] = ` "{ - \\"singleQuote\\": true, - \\"proseWrap\\": \\"never\\", - \\"trailingComma\\": \\"es5\\" + "singleQuote": true, + "proseWrap": "never", + "trailingComma": "es5" }" `; -exports[`Templates JavaScript Helper File content: README.md 1`] = ` +exports[`Templates > JavaScript Helper > File content > README.md 1`] = ` "# javascript-helper-app _This project was generated with [create-instantsearch-app](https://github.com/algolia/instantsearch/tree/master/packages/create-instantsearch-app) by [Algolia](https://algolia.com)._ @@ -3666,88 +3666,88 @@ yarn start Open http://localhost:3000 to see your app." `; -exports[`Templates JavaScript Helper File content: index.html 1`] = ` +exports[`Templates > JavaScript Helper > File content > index.html 1`] = ` " - + - - - + + + - - + + - - + + javascript-helper-app -
      -

      - javascript-helper-app +
      +

      + javascript-helper-app

      -

      using the - Algolia Search Helper for JavaScript +

      using the + Algolia Search Helper for JavaScript

      -
      -
      -
      -
      - +
      +
      + -
      +
      - + " `; -exports[`Templates JavaScript Helper File content: manifest.webmanifest 1`] = ` +exports[`Templates > JavaScript Helper > File content > manifest.webmanifest 1`] = ` "{ - \\"short_name\\": \\"javascript-helper-app\\", - \\"name\\": \\"javascript-helper-app Sample\\", - \\"icons\\": [ + "short_name": "javascript-helper-app", + "name": "javascript-helper-app Sample", + "icons": [ { - \\"src\\": \\"favicon.png\\", - \\"sizes\\": \\"64x64 32x32 24x24 16x16\\", - \\"type\\": \\"image/x-icon\\" + "src": "favicon.png", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" } ], - \\"start_url\\": \\"./index.html\\", - \\"display\\": \\"standalone\\", - \\"theme_color\\": \\"#000000\\", - \\"background_color\\": \\"#ffffff\\" + "start_url": "./index.html", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" }" `; -exports[`Templates JavaScript Helper File content: package.json 1`] = ` +exports[`Templates > JavaScript Helper > File content > package.json 1`] = ` "{ - \\"name\\": \\"javascript-helper-app\\", - \\"version\\": \\"1.0.0\\", - \\"private\\": true, - \\"main\\": \\"src/app.js\\", - \\"scripts\\": { - \\"start\\": \\"parcel index.html --port 3000\\", - \\"build\\": \\"parcel build index.html\\", - \\"lint\\": \\"eslint .\\", - \\"lint:fix\\": \\"npm run lint -- --fix\\" + "name": "javascript-helper-app", + "version": "1.0.0", + "private": true, + "main": "src/app.js", + "scripts": { + "start": "parcel index.html --port 3000", + "build": "parcel build index.html", + "lint": "eslint .", + "lint:fix": "npm run lint -- --fix" }, - \\"partialDependencies\\": { - \\"algoliasearch-helper\\": \\"3.0.0\\" + "partialDependencies": { + "algoliasearch-helper": "3.0.0" } }" `; -exports[`Templates JavaScript Helper File content: src/app.css 1`] = ` +exports[`Templates > JavaScript Helper > File content > src/app.css 1`] = ` "em { background: cyan; font-style: normal; @@ -3833,7 +3833,7 @@ exports[`Templates JavaScript Helper File content: src/app.css 1`] = ` }" `; -exports[`Templates JavaScript Helper File content: src/app.js 1`] = ` +exports[`Templates > JavaScript Helper > File content > src/app.js 1`] = ` "import algoliasearch from 'algoliasearch'; import algoliasearchHelper from 'algoliasearch-helper'; @@ -3852,13 +3852,13 @@ $searchBox.addEventListener('input', (event) => { helper.on('result', ({ results }) => { // Please sanitize user-provided data when using \`innerHTML\` to avoid XSS $hits.innerHTML = \` -
        +
          \${results.hits .map( (hit) => - \`
        1. + \`
        2. - \\"\${hit.attribute1}\\" + \${hit.attribute1}

          \${hit._highlightResult.attribute1.value}

          \${hit._highlightResult.attribute2.value}

          @@ -3873,7 +3873,7 @@ helper.on('result', ({ results }) => { helper.search();" `; -exports[`Templates JavaScript Helper File content: src/index.css 1`] = ` +exports[`Templates > JavaScript Helper > File content > src/index.css 1`] = ` "body, h1 { margin: 0; @@ -3886,8 +3886,8 @@ body { }" `; -exports[`Templates JavaScript Helper Folder structure: contains the right files 1`] = ` -Array [ +exports[`Templates > JavaScript Helper > Folder structure > contains the right files 1`] = ` +[ ".editorconfig", ".eslintignore", ".eslintrc.js", @@ -3904,7 +3904,7 @@ Array [ ] `; -exports[`Templates React InstantSearch File content: .editorconfig 1`] = ` +exports[`Templates > React InstantSearch > File content > .editorconfig 1`] = ` "root = true [*] @@ -3915,7 +3915,7 @@ insert_final_newline = true trim_trailing_whitespace = true" `; -exports[`Templates React InstantSearch File content: .gitignore 1`] = ` +exports[`Templates > React InstantSearch > File content > .gitignore 1`] = ` "# Logs logs *.log @@ -3941,15 +3941,15 @@ dist *.sw?" `; -exports[`Templates React InstantSearch File content: .prettierrc 1`] = ` +exports[`Templates > React InstantSearch > File content > .prettierrc 1`] = ` "{ - \\"singleQuote\\": true, - \\"proseWrap\\": \\"never\\", - \\"trailingComma\\": \\"es5\\" + "singleQuote": true, + "proseWrap": "never", + "trailingComma": "es5" }" `; -exports[`Templates React InstantSearch File content: README.md 1`] = ` +exports[`Templates > React InstantSearch > File content > README.md 1`] = ` "# react-instantsearch-app _This project was generated with [create-instantsearch-app](https://github.com/algolia/instantsearch/tree/master/packages/create-instantsearch-app) by [Algolia](https://algolia.com)._ @@ -3971,25 +3971,25 @@ yarn start \`\`\`" `; -exports[`Templates React InstantSearch File content: index.html 1`] = ` +exports[`Templates > React InstantSearch > File content > index.html 1`] = ` " - + - + - + react-instantsearch-app @@ -3998,29 +3998,29 @@ exports[`Templates React InstantSearch File content: index.html 1`] = ` -
          +
          - + " `; -exports[`Templates React InstantSearch File content: package.json 1`] = ` +exports[`Templates > React InstantSearch > File content > package.json 1`] = ` "{ - \\"name\\": \\"react-instantsearch-app\\", - \\"version\\": \\"1.0.0\\", - \\"private\\": true, - \\"scripts\\": { - \\"build\\": \\"parcel build index.html\\", - \\"start\\": \\"parcel index.html\\" + "name": "react-instantsearch-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "parcel build index.html", + "start": "parcel index.html" }, - \\"partialDependencies\\": { - \\"react-instantsearch\\": \\"7.0.0\\" + "partialDependencies": { + "react-instantsearch": "7.0.0" } }" `; -exports[`Templates React InstantSearch File content: src/App.css 1`] = ` +exports[`Templates > React InstantSearch > File content > src/App.css 1`] = ` "body, h1 { margin: 0; @@ -4103,7 +4103,7 @@ em { }" `; -exports[`Templates React InstantSearch File content: src/App.tsx 1`] = ` +exports[`Templates > React InstantSearch > File content > src/App.tsx 1`] = ` "import React from 'react'; import algoliasearch from 'algoliasearch/lite'; import { @@ -4130,46 +4130,46 @@ const future = { preserveSharedStateOnUnmount: true }; export function App() { return (
          -
          -

          - react-instantsearch-app +
          +

          + react-instantsearch-app

          -

          +

          using{' '} - + React InstantSearch

          -
          +
          -
          -
          +
          +
          - - + + - - + +
          -
          +
          -
          +
          @@ -4190,10 +4190,10 @@ function Hit({ hit }: HitProps) { {hit.attribute1}

          - +

          - +

          @@ -4201,7 +4201,7 @@ function Hit({ hit }: HitProps) { }" `; -exports[`Templates React InstantSearch File content: src/Panel.tsx 1`] = ` +exports[`Templates > React InstantSearch > File content > src/Panel.tsx 1`] = ` "import React from 'react'; type PanelProps = React.PropsWithChildren<{ @@ -4210,17 +4210,17 @@ type PanelProps = React.PropsWithChildren<{ export function Panel({ header, children }: PanelProps) { return ( -
          -
          +
          +
          {header}
          -
          {children}
          +
          {children}
          ); }" `; -exports[`Templates React InstantSearch File content: src/index.tsx 1`] = ` +exports[`Templates > React InstantSearch > File content > src/index.tsx 1`] = ` "import React from 'react'; import { createRoot } from 'react-dom/client'; @@ -4229,8 +4229,8 @@ import { App } from './App'; createRoot(document.getElementById('root')!).render();" `; -exports[`Templates React InstantSearch Folder structure: contains the right files 1`] = ` -Array [ +exports[`Templates > React InstantSearch > Folder structure > contains the right files 1`] = ` +[ ".editorconfig", ".gitignore", ".prettierrc", @@ -4245,14 +4245,14 @@ Array [ ] `; -exports[`Templates React InstantSearch Native File content: .expo-shared/assets.json 1`] = ` +exports[`Templates > React InstantSearch Native > File content > .expo-shared/assets.json 1`] = ` "{ - \\"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb\\": true, - \\"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd\\": true + "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, + "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true }" `; -exports[`Templates React InstantSearch Native File content: .gitignore 1`] = ` +exports[`Templates > React InstantSearch Native > File content > .gitignore 1`] = ` "node_modules/ .expo/ dist/ @@ -4269,7 +4269,7 @@ web-build/ .DS_Store" `; -exports[`Templates React InstantSearch Native File content: App.tsx 1`] = ` +exports[`Templates > React InstantSearch Native > File content > App.tsx 1`] = ` "import React, { useRef } from 'react'; import { FlatList, SafeAreaView, StyleSheet, Text, View } from 'react-native'; import { StatusBar } from 'expo-status-bar'; @@ -4291,9 +4291,9 @@ export default function App() { return ( - + - + listRef.current?.scrollToOffset({ animated: false, offset: 0 }) @@ -4314,10 +4314,10 @@ function Hit({ hit }: HitProps) { return ( <> - + - + ); @@ -4336,7 +4336,7 @@ const styles = StyleSheet.create({ });" `; -exports[`Templates React InstantSearch Native File content: README.md 1`] = ` +exports[`Templates > React InstantSearch Native > File content > README.md 1`] = ` "# react-instantsearch-native-app _This project was generated with [create-instantsearch-app](https://github.com/algolia/instantsearch/tree/master/packages/create-instantsearch-app) by [Algolia](https://algolia.com)._ @@ -4358,40 +4358,40 @@ yarn start \`\`\`" `; -exports[`Templates React InstantSearch Native File content: app.json 1`] = ` +exports[`Templates > React InstantSearch Native > File content > app.json 1`] = ` "{ - \\"expo\\": { - \\"name\\": \\"react-instantsearch-native-app\\", - \\"slug\\": \\"react-instantsearch-native-app\\", - \\"version\\": \\"1.0.0\\", - \\"orientation\\": \\"portrait\\", - \\"icon\\": \\"./assets/icon.png\\", - \\"splash\\": { - \\"image\\": \\"./assets/splash.png\\", - \\"resizeMode\\": \\"contain\\", - \\"backgroundColor\\": \\"#ffffff\\" + "expo": { + "name": "react-instantsearch-native-app", + "slug": "react-instantsearch-native-app", + "version": "1.0.0", + "orientation": "portrait", + "icon": "./assets/icon.png", + "splash": { + "image": "./assets/splash.png", + "resizeMode": "contain", + "backgroundColor": "#ffffff" }, - \\"updates\\": { - \\"fallbackToCacheTimeout\\": 0 + "updates": { + "fallbackToCacheTimeout": 0 }, - \\"assetBundlePatterns\\": [\\"**/*\\"], - \\"ios\\": { - \\"supportsTablet\\": true + "assetBundlePatterns": ["**/*"], + "ios": { + "supportsTablet": true }, - \\"android\\": { - \\"adaptiveIcon\\": { - \\"foregroundImage\\": \\"./assets/adaptive-icon.png\\", - \\"backgroundColor\\": \\"#FFFFFF\\" + "android": { + "adaptiveIcon": { + "foregroundImage": "./assets/adaptive-icon.png", + "backgroundColor": "#FFFFFF" } }, - \\"web\\": { - \\"favicon\\": \\"./assets/favicon.png\\" + "web": { + "favicon": "./assets/favicon.png" } } }" `; -exports[`Templates React InstantSearch Native File content: babel.config.js 1`] = ` +exports[`Templates > React InstantSearch Native > File content > babel.config.js 1`] = ` "module.exports = function (api) { api.cache(true); return { @@ -4400,26 +4400,26 @@ exports[`Templates React InstantSearch Native File content: babel.config.js 1`] };" `; -exports[`Templates React InstantSearch Native File content: package.json 1`] = ` +exports[`Templates > React InstantSearch Native > File content > package.json 1`] = ` "{ - \\"name\\": \\"react-instantsearch-native-app\\", - \\"version\\": \\"1.0.0\\", - \\"private\\": true, - \\"main\\": \\"node_modules/expo/AppEntry.js\\", - \\"scripts\\": { - \\"start\\": \\"expo start\\", - \\"android\\": \\"expo start --android\\", - \\"ios\\": \\"expo start --ios\\", - \\"web\\": \\"expo start --web\\", - \\"eject\\": \\"expo eject\\" + "name": "react-instantsearch-native-app", + "version": "1.0.0", + "private": true, + "main": "node_modules/expo/AppEntry.js", + "scripts": { + "start": "expo start", + "android": "expo start --android", + "ios": "expo start --ios", + "web": "expo start --web", + "eject": "expo eject" }, - \\"partialDependencies\\": { - \\"react-instantsearch-core\\": \\"7.0.0\\" + "partialDependencies": { + "react-instantsearch-core": "7.0.0" } }" `; -exports[`Templates React InstantSearch Native File content: src/Highlight.tsx 1`] = ` +exports[`Templates > React InstantSearch Native > File content > src/Highlight.tsx 1`] = ` "import React, { Fragment } from 'react'; import { StyleSheet, Text } from 'react-native'; import { Hit as AlgoliaHit } from '@algolia/client-search'; @@ -4503,7 +4503,7 @@ const styles = StyleSheet.create({ });" `; -exports[`Templates React InstantSearch Native File content: src/InfiniteHits.tsx 1`] = ` +exports[`Templates > React InstantSearch Native > File content > src/InfiniteHits.tsx 1`] = ` "import React, { forwardRef } from 'react'; import { StyleSheet, View, FlatList } from 'react-native'; import { Hit as AlgoliaHit } from '@algolia/client-search'; @@ -4562,7 +4562,7 @@ declare module 'react' { }" `; -exports[`Templates React InstantSearch Native File content: src/SearchBox.tsx 1`] = ` +exports[`Templates > React InstantSearch Native > File content > src/SearchBox.tsx 1`] = ` "import React, { useEffect, useRef, useState } from 'react'; import { StyleSheet, View, TextInput } from 'react-native'; import { useSearchBox, UseSearchBoxProps } from 'react-instantsearch-core'; @@ -4608,12 +4608,12 @@ export function SearchBox({ onChange, ...props }: SearchBoxProps) { setValue(newValue); onChange(newValue); }} - clearButtonMode=\\"while-editing\\" - autoCapitalize=\\"none\\" + clearButtonMode="while-editing" + autoCapitalize="none" autoCorrect={false} spellCheck={false} - autoCompleteType=\\"off\\" - placeholder=\\"Search placeholder\\" + autoCompleteType="off" + placeholder="Search placeholder" /> ); @@ -4636,16 +4636,16 @@ const styles = StyleSheet.create({ });" `; -exports[`Templates React InstantSearch Native File content: tsconfig.json 1`] = ` +exports[`Templates > React InstantSearch Native > File content > tsconfig.json 1`] = ` "{ - \\"extends\\": \\"expo/tsconfig.base\\", - \\"compilerOptions\\": { - \\"strict\\": true + "extends": "expo/tsconfig.base", + "compilerOptions": { + "strict": true } }" `; -exports[`Templates React InstantSearch Native File content: types/ProductHit.ts 1`] = ` +exports[`Templates > React InstantSearch Native > File content > types/ProductHit.ts 1`] = ` "import { Hit as AlgoliaHit } from 'instantsearch.js'; export type ProductHit = AlgoliaHit<{ @@ -4676,8 +4676,8 @@ export type ProductHit = AlgoliaHit<{ }>;" `; -exports[`Templates React InstantSearch Native Folder structure: contains the right files 1`] = ` -Array [ +exports[`Templates > React InstantSearch Native > Folder structure > contains the right files 1`] = ` +[ ".expo-shared/assets.json", ".gitignore", "App.tsx", @@ -4697,7 +4697,7 @@ Array [ ] `; -exports[`Templates Vue InstantSearch File content: .editorconfig 1`] = ` +exports[`Templates > Vue InstantSearch > File content > .editorconfig 1`] = ` "root = true [*] @@ -4709,7 +4709,7 @@ insert_final_newline = true trim_trailing_whitespace = true" `; -exports[`Templates Vue InstantSearch File content: .eslintrc.js 1`] = ` +exports[`Templates > Vue InstantSearch > File content > .eslintrc.js 1`] = ` "module.exports = { // extends from 'prettier/vue' until we update the Algolia configuration extends: ['algolia/vue', 'prettier/vue'], @@ -4721,7 +4721,7 @@ exports[`Templates Vue InstantSearch File content: .eslintrc.js 1`] = ` };" `; -exports[`Templates Vue InstantSearch File content: .gitignore 1`] = ` +exports[`Templates > Vue InstantSearch > File content > .gitignore 1`] = ` ".DS_Store node_modules /dist @@ -4745,15 +4745,15 @@ yarn-error.log* *.sw?" `; -exports[`Templates Vue InstantSearch File content: .prettierrc 1`] = ` +exports[`Templates > Vue InstantSearch > File content > .prettierrc 1`] = ` "{ - \\"singleQuote\\": true, - \\"proseWrap\\": \\"never\\", - \\"trailingComma\\": \\"es5\\" + "singleQuote": true, + "proseWrap": "never", + "trailingComma": "es5" }" `; -exports[`Templates Vue InstantSearch File content: README.md 1`] = ` +exports[`Templates > Vue InstantSearch > File content > README.md 1`] = ` "# vue-instantsearch-app _This project was generated with [create-instantsearch-app](https://github.com/algolia/instantsearch/tree/master/packages/create-instantsearch-app) by [Algolia](https://algolia.com)._ @@ -4777,49 +4777,49 @@ yarn start Open http://localhost:3000 to see your app." `; -exports[`Templates Vue InstantSearch File content: babel.config.js 1`] = ` +exports[`Templates > Vue InstantSearch > File content > babel.config.js 1`] = ` "module.exports = { presets: ['@vue/app'], };" `; -exports[`Templates Vue InstantSearch File content: package.json 1`] = ` +exports[`Templates > Vue InstantSearch > File content > package.json 1`] = ` "{ - \\"name\\": \\"vue-instantsearch-app\\", - \\"version\\": \\"1.0.0\\", - \\"private\\": true, - \\"scripts\\": { - \\"start\\": \\"NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve --port 3000\\", - \\"build\\": \\"NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build\\", - \\"lint\\": \\"NODE_OPTIONS=--openssl-legacy-provider vue-cli-service lint\\", - \\"lint:fix\\": \\"npm run lint -- --fix\\" + "name": "vue-instantsearch-app", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve --port 3000", + "build": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build", + "lint": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service lint", + "lint:fix": "npm run lint -- --fix" }, - \\"browserslist\\": [ - \\"> 1%\\", - \\"last 2 versions\\", - \\"not ie <= 8\\" + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 8" ], - \\"partialDependencies\\": { - \\"vue-instantsearch\\": \\"3.0.0\\" + "partialDependencies": { + "vue-instantsearch": "3.0.0" } }" `; -exports[`Templates Vue InstantSearch File content: public/index.html 1`] = ` +exports[`Templates > Vue InstantSearch > File content > public/index.html 1`] = ` " - + - - - - favicon.png\\" /> + + + + vue-instantsearch-app @@ -4830,71 +4830,71 @@ exports[`Templates Vue InstantSearch File content: public/index.html 1`] = ` enabled. Please enable it to continue. -
          +
          " `; -exports[`Templates Vue InstantSearch File content: src/App.vue 1`] = ` +exports[`Templates > Vue InstantSearch > File content > src/App.vue 1`] = ` "
          `; -exports[`RangeInput expect to render with values 1`] = ` +exports[`RangeInput > expect to render with values 1`] = `
          @@ -200,7 +240,16 @@ exports[`RangeInput expect to render with values 1`] = ` } templatesConfig={{}} useCustomCompileOptions={{}} - /> + > + +
          `; -exports[`RangeInput willReceiveProps expect to update the empty state from given props 1`] = ` +exports[`RangeInput > willReceiveProps > expect to update the empty state from given props 1`] = `
          @@ -280,7 +340,16 @@ exports[`RangeInput willReceiveProps expect to update the empty state from given } templatesConfig={{}} useCustomCompileOptions={{}} - /> + > + +
          `; -exports[`RangeInput willReceiveProps expect to update the empty state from given props 2`] = ` +exports[`RangeInput > willReceiveProps > expect to update the empty state from given props 2`] = `
          @@ -360,7 +440,16 @@ exports[`RangeInput willReceiveProps expect to update the empty state from given } templatesConfig={{}} useCustomCompileOptions={{}} - /> + > + +
          `; -exports[`RangeInput willReceiveProps expect to update the state from given props 1`] = ` +exports[`RangeInput > willReceiveProps > expect to update the state from given props 1`] = `
          @@ -440,7 +540,16 @@ exports[`RangeInput willReceiveProps expect to update the state from given props } templatesConfig={{}} useCustomCompileOptions={{}} - /> + > + +
          `; -exports[`RangeInput willReceiveProps expect to update the state from given props 2`] = ` +exports[`RangeInput > willReceiveProps > expect to update the state from given props 2`] = `
          @@ -520,7 +640,16 @@ exports[`RangeInput willReceiveProps expect to update the state from given props } templatesConfig={{}} useCustomCompileOptions={{}} - /> + > + +
          `; diff --git a/packages/instantsearch.js/src/components/RefinementList/__tests__/RefinementList-test.tsx b/packages/instantsearch.js/src/components/RefinementList/__tests__/RefinementList-test.tsx index 2c2ed3a7a0f..b0ffbdf0aea 100644 --- a/packages/instantsearch.js/src/components/RefinementList/__tests__/RefinementList-test.tsx +++ b/packages/instantsearch.js/src/components/RefinementList/__tests__/RefinementList-test.tsx @@ -1,5 +1,5 @@ /** - * @jest-environment @instantsearch/testutils/jest-environment-jsdom.ts + * @vitest-environment happy-dom */ /** @jsx h */ @@ -298,7 +298,7 @@ describe('RefinementList', () => { describe('sublist', () => { it('should create a subList with the sub values', () => { - const toggleRefinement = jest.fn(); + const toggleRefinement = vi.fn(); const props: RefinementListProps = { ...defaultProps, toggleRefinement, @@ -653,7 +653,7 @@ describe('RefinementList', () => { }); it('should not refine on click on already refined items', () => { - const toggleRefinement = jest.fn(); + const toggleRefinement = vi.fn(); const templates = { item: (item: RefinementListItemData) => ` diff --git a/packages/instantsearch.js/src/components/RefinementList/__tests__/RefinementListItem-test.tsx b/packages/instantsearch.js/src/components/RefinementList/__tests__/RefinementListItem-test.tsx index 3a888f47e1d..6006135f48c 100644 --- a/packages/instantsearch.js/src/components/RefinementList/__tests__/RefinementListItem-test.tsx +++ b/packages/instantsearch.js/src/components/RefinementList/__tests__/RefinementListItem-test.tsx @@ -1,5 +1,5 @@ /** - * @jest-environment @instantsearch/testutils/jest-environment-jsdom.ts + * @vitest-environment happy-dom */ /** @jsx h */ @@ -10,11 +10,15 @@ import RefinementListItem from '../RefinementListItem'; import type { RefinementListItemProps } from '../RefinementListItem'; +vi.mock('../../Template/Template', () => ({ + default: (props: any) =>
          , +})); + describe('RefinementListItem', () => { const props: RefinementListItemProps = { facetValueToRefine: 'wi', isRefined: false, - handleClick: jest.fn(), + handleClick: vi.fn(), className: 'item class', templateData: { template: 'data' }, templateKey: 'item key', diff --git a/packages/instantsearch.js/src/components/RefinementList/__tests__/__snapshots__/RefinementList-test.tsx.snap b/packages/instantsearch.js/src/components/RefinementList/__tests__/__snapshots__/RefinementList-test.tsx.snap index 95851944516..038ee896371 100644 --- a/packages/instantsearch.js/src/components/RefinementList/__tests__/__snapshots__/RefinementList-test.tsx.snap +++ b/packages/instantsearch.js/src/components/RefinementList/__tests__/__snapshots__/RefinementList-test.tsx.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`RefinementList rendering with facets 1`] = ` +exports[`RefinementList > rendering > with facets 1`] = `
          `; -exports[`RefinementList rendering with facets and disabled show more 1`] = ` +exports[`RefinementList > rendering > with facets and disabled show more 1`] = `
          `; -exports[`RefinementList rendering with facets and show more 1`] = ` +exports[`RefinementList > rendering > with facets and show more 1`] = `
          `; -exports[`RefinementList rendering with facets from search 1`] = ` +exports[`RefinementList > rendering > with facets from search 1`] = `
          `; -exports[`RefinementList rendering without facets 1`] = ` +exports[`RefinementList > rendering > without facets 1`] = `
          `; -exports[`RefinementList rendering without facets from search 1`] = ` +exports[`RefinementList > rendering > without facets from search 1`] = `
          renders an item 1`] = `
        3. -