Skip to content

Commit

Permalink
Merge branch 'master' into test/KIT-3578
Browse files Browse the repository at this point in the history
  • Loading branch information
alexprudhomme authored Sep 25, 2024
2 parents a0671d0 + b595d0d commit e64f1c7
Show file tree
Hide file tree
Showing 21 changed files with 200 additions and 79 deletions.
1 change: 1 addition & 0 deletions packages/atomic/stencil.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const isDevWatch: boolean =
process.argv.indexOf('--watch') > -1;

export const config: Config = {
tsconfig: 'tsconfig.stencil.json',
namespace: 'atomic',
taskQueue: 'async',
sourceMap: true,
Expand Down
26 changes: 2 additions & 24 deletions packages/atomic/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,10 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": false,
"experimentalDecorators": true,
"lib": ["dom", "ES2023", "ESNext.Collection"],
"moduleResolution": "Bundler",
"module": "ES2022",
"target": "ES2021",
"resolveJsonModule": true,
"useDefineForClassFields": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"jsx": "react",
"jsxFactory": "h"
},
"references": [
{
"path": "./tsconfig.storybook.json"
}
],
"include": ["src", "types/jsx.d.ts"],
"extends": "./tsconfig.stencil.json",
"exclude": [
"node_modules",
"src/external-builds",
"**/*.stories.tsx",
"**/*.stories.ts",
"**/*.stories.js",
"**/e2e/**/*"
"**/*.stories.js"
]
}
32 changes: 32 additions & 0 deletions packages/atomic/tsconfig.stencil.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": false,
"experimentalDecorators": true,
"lib": ["dom", "ES2023", "ESNext.Collection"],
"moduleResolution": "Bundler",
"module": "ES2022",
"target": "ES2021",
"resolveJsonModule": true,
"useDefineForClassFields": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"jsx": "react",
"jsxFactory": "h"
},
"references": [
{
"path": "./tsconfig.storybook.json"
}
],
"include": ["src", "types/jsx.d.ts"],
"exclude": [
"node_modules",
"src/external-builds",
"**/*.stories.tsx",
"**/*.stories.ts",
"**/*.stories.js",
"**/e2e/**/*"
]
}
36 changes: 35 additions & 1 deletion packages/headless-react/src/ssr/search-engine.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import {NavigatorContextProvider} from '@coveo/headless/dist/definitions/app/navigatorContextProvider.js';
import {
getSampleSearchEngineConfiguration,
InferStaticState,
InferHydratedState,
defineResultList,
defineSearchBox,
Result,
NavigatorContextProvider,
} from '@coveo/headless/ssr';
import {act, render, renderHook, screen} from '@testing-library/react';
import {randomUUID} from 'crypto';
import {PropsWithChildren} from 'react';
import React from 'react';
import {
vi,
expect,
Expand Down Expand Up @@ -106,7 +109,38 @@ describe('Headless react SSR utils', () => {
} = engineDefinition;

function TestResultList() {
const generateMockResult: () => Result = () => {
return {
absentTerms: [],
clickUri: '',
excerpt: '',
excerptHighlights: [],
firstSentences: '',
firstSentencesHighlights: [],
flags: '',
hasHtmlVersion: false,
isRecommendation: false,
isTopResult: false,
isUserActionView: false,
percentScore: 0,
printableUri: '',
printableUriHighlights: [],
rankingInfo: null,
raw: {urihash: ''},
score: 0,
searchUid: '',
summary: null,
summaryHighlights: [],
title: '',
titleHighlights: [],
uniqueId: randomUUID(),
uri: '',
};
};

const {state} = controllers.useResultList();

state.results = Array.from({length: numResults}, generateMockResult);
return (
<ul>
{state.results.map((result) => (
Expand Down
54 changes: 33 additions & 21 deletions packages/headless/contributors/adding-a-sub-package.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Adding a sub-package

Headless provides exports through multiple sub packages. A sub-package groups together exports (i.e. controllers, actions, reducers, engines) that work together as a cohesive unit. By separating exports into sub-packages, it becomes clear to users of headless what exports are available to build a use-case.
Headless provides exports through multiple sub-packages.

A sub-package groups together exports (i.e. engine, controllers, action loaders, selectors, types, utilities) that work together as a cohesive unit. By separating exports into sub-packages, it becomes clear to users of Headless what exports are available to build a specific use-case.

## To add a new sub-package:

1. Create an entry file for your sub-package inside the `src` directory (e.g. `case-assist.index.ts`).
2. Configure nodejs and browser bundles inside `esbuild.mjs` for the entry file created in step #1. Add entries in `useCaseEntries` and `getUmdGlobalName` map for the global name (used to store exports for iife)
1. In the `headless/src` directory, create an entry file for your new sub-package (e.g. `headless/src/case-assist.index.ts`). Everything you export from this file will be part of the public API of your sub-package.
2. In `headless/esbuild.mjs`, Configure NodeJS add entries for your new sub-package in the `useCaseEntries` object and `getUmdGlobalName` function map.

```javascript
// headless/esbuild.mjs
Expand All @@ -19,12 +21,12 @@ Headless provides exports through multiple sub packages. A sub-package groups to
// ...
};

// ...

function getUmdGlobalName(useCase) {
const map = {
search: 'CoveoHeadless',
recommendation: 'CoveoHeadlessRecommendation',
'product-recommendation': 'CoveoHeadlessProductRecommendation',
'product-listing': 'CoveoHeadlessProductListing',
'case-assist': 'CoveoHeadlessCaseAssist',
// ...
};
Expand All @@ -33,23 +35,33 @@ Headless provides exports through multiple sub packages. A sub-package groups to
}
```

3. Create a new directory with the name of your sub-package at the `headless/` root.
4. Inside the new directory, add a `package.json` file. Add the paths to your bundled files and type definitions. Make sure to mark the package as `private` so it doesn't get published individually.
```json
{
"private": true,
"name": "case-assist",
"description": "Headless Case Assist Module",
"main": "../dist/case-assist/headless.js",
"module": "../dist/case-assist/headless.esm.js",
"browser": "../dist/browser/case-assist/headless.esm.js",
"types": "../dist/definitions/case-assist.index.d.ts",
"license": "Apache-2.0"
}
```
3. In `headless/package.json`, add an entry point for your sub-package in the `exports` object.

5. Add the directory name to the `files` array in the project root `package.json` file.
````json
// headless/package.json

// ...
"exports": {
// ...
"./case-assist": {
"types": "./dist/definitions/case-assist.index.d.ts",
"node": {
"types": "./dist/definitions/case-assist.index.d.ts",
"import": "./dist/case-assist/headless.esm.js",
"require": "./dist/case-assist/headless.cjs"
},
"browser": {
"types": "./dist/definitions/case-assist.index.d.ts",
"import": "./dist/browser/case-assist/headless.esm.js",
"require": "./dist/browser/case-assist/headless.js"
},
"import": "./dist/browser/case-assist/headless.esm.js",
"require": "./dist/browser/case-assist/headless.js"
},
// ...
}
``` 
````
## Testing your sub-package:
Expand Down
2 changes: 0 additions & 2 deletions packages/headless/esbuild.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ function getUmdGlobalName(useCase) {
const map = {
search: 'CoveoHeadless',
recommendation: 'CoveoHeadlessRecommendation',
'product-recommendation': 'CoveoHeadlessProductRecommendation',
'product-listing': 'CoveoHeadlessProductListing',
'case-assist': 'CoveoHeadlessCaseAssist',
insight: 'CoveoHeadlessInsight',
ssr: 'CoveoHeadlessSSR',
Expand Down
6 changes: 4 additions & 2 deletions packages/headless/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@
"build:bundles": "node esbuild.mjs",
"build:definitions": "tsc -p src/tsconfig.build.json -d --emitDeclarationOnly --declarationDir dist/definitions",
"clean": "rimraf -rf dist/*",
"test": "vitest run",
"test:watch": "vitest",
"test": "vitest run --exclude \"src/integration-tests/**\"",
"test:watch": "vitest --exclude \"src/integration-tests/**\"",
"integration-test": "vitest run --poolOptions.threads.singleThread src/integration-tests/**",
"integration-test:watch": "vitest --poolOptions.threads.singleThread src/integration-tests/**",
"publish:npm": "npm run-script -w=@coveo/release npm-publish",
"publish:bump": "npm run-script -w=@coveo/release bump",
"promote:npm:latest": "node ../../scripts/deploy/update-npm-tag.mjs latest",
Expand Down
31 changes: 12 additions & 19 deletions packages/headless/src/app/search-engine/search-engine.ssr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,6 @@ describe('SSR', () => {
);
}

function getResultsCount(state: AnyState) {
return state.controllers.resultList.state.results.length;
}

beforeEach(() => {
engineDefinition = defineSearchEngine({
configuration: {
Expand Down Expand Up @@ -147,27 +143,27 @@ describe('SSR', () => {
});

it('fetches initial state of engine', async () => {
const {fetchStaticState} = engineDefinition;
const fetchStaticState = vi.mocked(engineDefinition.fetchStaticState);
const staticState = await fetchStaticState();
expect(staticState).toBeTruthy();
expect(getResultsCount(staticState)).toBe(defaultNumberOfResults);
expect(getResultsPerPage(staticState)).toBe(defaultNumberOfResults);
});

describe('with a static state', () => {
let staticState: StaticState;
beforeEach(async () => {
const {fetchStaticState} = engineDefinition;
const fetchStaticState = vi.mocked(engineDefinition.fetchStaticState);
staticState = await fetchStaticState();
});

it('hydrates engine and fetches results using hydrated engine', async () => {
const {hydrateStaticState} = engineDefinition;
it('hydrates engine', async () => {
const hydrateStaticState = vi.mocked(
engineDefinition.hydrateStaticState
);
const hydratedState = await hydrateStaticState(staticState);
expect(hydratedState.engine.state.configuration.organizationId).toEqual(
getSampleSearchEngineConfiguration().organizationId
);
expect(getResultsCount(hydratedState)).toBe(defaultNumberOfResults);
expect(getResultsPerPage(hydratedState)).toBe(defaultNumberOfResults);
});
});
Expand All @@ -176,7 +172,7 @@ describe('SSR', () => {
const newNumberOfResults = 6;

async function fetchBuildResultWithNewNumberOfResults() {
const {build} = engineDefinition;
const build = vi.mocked(engineDefinition.build);
const buildResult = await build();
const {registerNumberOfResults} = loadPaginationActions(
buildResult.engine
Expand All @@ -189,33 +185,30 @@ describe('SSR', () => {
}

it('fetches initial state of engine from build result', async () => {
const {fetchStaticState} = engineDefinition;
const fetchStaticState = vi.mocked(engineDefinition.fetchStaticState);
const staticState = await fetchStaticState.fromBuildResult({
buildResult: await fetchBuildResultWithNewNumberOfResults(),
});
expect(staticState).toBeTruthy();
expect(getResultsCount(staticState)).toBe(newNumberOfResults);
expect(getResultsPerPage(staticState)).toBe(newNumberOfResults);
});

describe('with the default static state', () => {
let staticState: StaticState;
beforeEach(async () => {
const {fetchStaticState} = engineDefinition;
const fetchStaticState = vi.mocked(engineDefinition.fetchStaticState);
staticState = await fetchStaticState();
});

it('hydrates engine from build result', async () => {
const {hydrateStaticState} = engineDefinition;
const hydrateStaticState = vi.mocked(
engineDefinition.hydrateStaticState
);
const buildResult = await fetchBuildResultWithNewNumberOfResults();
const hydratedState = await hydrateStaticState.fromBuildResult({
buildResult: buildResult,
searchAction: staticState.searchAction,
});
expect(getResultsCount(staticState)).toBe(defaultNumberOfResults);
expect(getResultsCount(hydratedState)).toBe(
getResultsCount(staticState)
);
expect(getResultsPerPage(hydratedState)).toBe(newNumberOfResults);
});
});
Expand Down
1 change: 1 addition & 0 deletions packages/headless/src/ssr.index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export type {SortDefinition} from './controllers/sort/headless-sort.ssr.js';
export type {StandaloneSearchBoxDefinition} from './controllers/standalone-search-box/headless-standalone-search-box.ssr.js';
export type {StaticFilterDefinition} from './controllers/static-filter/headless-static-filter.ssr.js';
export type {TabDefinition} from './controllers/tab/headless-tab.ssr.js';
export type {NavigatorContextProvider} from './app/navigatorContextProvider.js';

// export type
export type {CoreEngine, ExternalEngineOptions} from './app/engine.js';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
@isTest
public class OrganizationEndpointsTest {
@isTest
static void testGetOrganizationEndpointsWithProdEnv() {
String orgId = 'testOrgId';
String env = 'prod';

Map<String, String> endpoints = OrganizationEndpoints.getOrganizationEndpoints(orgId, env);

String expectedPlatform = 'https://testOrgId.org.coveo.com';
String expectedAnalytics = 'https://testOrgIdanalytics.org.coveo.com';
String expectedSearch = expectedPlatform + '/rest/search/v2';
String expectedAdmin = 'https://testOrgIdadmin.org.coveo.com';

System.assertEquals(expectedPlatform, endpoints.get('platform'), 'Platform URL mismatch for prod');
System.assertEquals(expectedAnalytics, endpoints.get('analytics'), 'Analytics URL mismatch for prod');
System.assertEquals(expectedSearch, endpoints.get('search'), 'Search URL mismatch for prod');
System.assertEquals(expectedAdmin, endpoints.get('admin'), 'Admin URL mismatch for prod');
}

@isTest
static void testGetOrganizationEndpointsWithNonProdEnv() {
String orgId = 'testOrgId';
String env = 'dev';

Map<String, String> endpoints = OrganizationEndpoints.getOrganizationEndpoints(orgId, env);

String expectedPlatform = 'https://testOrgId.orgdev.coveo.com';
String expectedAnalytics = 'https://testOrgIdanalytics.orgdev.coveo.com';
String expectedSearch = expectedPlatform + '/rest/search/v2';
String expectedAdmin = 'https://testOrgIdadmin.orgdev.coveo.com';

System.assertEquals(expectedPlatform, endpoints.get('platform'), 'Platform URL mismatch for dev');
System.assertEquals(expectedAnalytics, endpoints.get('analytics'), 'Analytics URL mismatch for dev');
System.assertEquals(expectedSearch, endpoints.get('search'), 'Search URL mismatch for dev');
System.assertEquals(expectedAdmin, endpoints.get('admin'), 'Admin URL mismatch for dev');
}

@isTest
static void testGetOrganizationEndpointsWithoutEnv() {
String orgId = 'testOrgId';

Map<String, String> endpoints = OrganizationEndpoints.getOrganizationEndpoints(orgId);

String expectedPlatform = 'https://testOrgId.org.coveo.com';
String expectedAnalytics = 'https://testOrgIdanalytics.org.coveo.com';
String expectedSearch = expectedPlatform + '/rest/search/v2';
String expectedAdmin = 'https://testOrgIdadmin.org.coveo.com';

System.assertEquals(expectedPlatform, endpoints.get('platform'), 'Platform URL mismatch');
System.assertEquals(expectedAnalytics, endpoints.get('analytics'), 'Analytics URL mismatch');
System.assertEquals(expectedSearch, endpoints.get('search'), 'Search URL mismatch');
System.assertEquals(expectedAdmin, endpoints.get('admin'), 'Admin URL mismatch');
}
}
Loading

0 comments on commit e64f1c7

Please sign in to comment.