Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
ab81891
Move bindings-context.ts
fbeaudoincoveo Sep 24, 2025
53f05ff
Merge branch 'main' into KIT-4997
fbeaudoincoveo Oct 7, 2025
154aa74
Improve component generation templates
fbeaudoincoveo Oct 10, 2025
ae1c272
Merge branch 'main' into KIT-4997
fbeaudoincoveo Oct 10, 2025
7a39b88
Add Prompt Engineer chatmode
fbeaudoincoveo Oct 15, 2025
1ce9ef2
Add prompt execution folder, readme and template
fbeaudoincoveo Oct 15, 2025
82e7a35
Adjust general instructions
fbeaudoincoveo Oct 15, 2025
1dcda2d
Adjust atomic instructions
fbeaudoincoveo Oct 15, 2025
ba65eab
Add e2e test generation prompt
fbeaudoincoveo Oct 15, 2025
db0cc4d
Add mdx generation prompt
fbeaudoincoveo Oct 15, 2025
0691c06
Improve prompts
fbeaudoincoveo Oct 15, 2025
05a9065
Merge branch 'main' into KIT-4997
fbeaudoincoveo Oct 16, 2025
fd91e66
Rename chatmode + add model
fbeaudoincoveo Oct 16, 2025
516b4a1
Fix typo
fbeaudoincoveo Oct 16, 2025
90ba01e
Fix imports
fbeaudoincoveo Oct 17, 2025
4ef1a49
Migrate atomic-result-number
fbeaudoincoveo Oct 17, 2025
62c526b
Improve prompts
fbeaudoincoveo Oct 17, 2025
07a7a66
Move + rework
fbeaudoincoveo Oct 20, 2025
fbf5afb
Set error to undefined when it's null
fbeaudoincoveo Oct 20, 2025
5e6d887
Add option to opt out of wrapping the component outside of the result…
fbeaudoincoveo Oct 20, 2025
3fd65d9
Add generated files
developer-experience-bot[bot] Oct 20, 2025
f977e1a
Merge branch 'main' into KIT-4997
fbeaudoincoveo Oct 21, 2025
7c7abf5
Do not impose model
fbeaudoincoveo Oct 21, 2025
4c8abef
Instruct to flag risky patterns in the chat
fbeaudoincoveo Oct 21, 2025
480b113
Fix list order
fbeaudoincoveo Oct 21, 2025
fad4b73
chore(atomic): migrate FacetPlaceholder (#6180)
fbeaudoincoveo Oct 27, 2025
ad8bfc8
Merge branch 'main' into KIT-4997
fbeaudoincoveo Oct 27, 2025
17b737b
Merge branch 'KIT-4997' into KIT-4974
fbeaudoincoveo Oct 27, 2025
3f9e037
Fix import path
fbeaudoincoveo Oct 27, 2025
f9f87eb
Improve docs
fbeaudoincoveo Oct 27, 2025
75826da
Fix stories
fbeaudoincoveo Oct 27, 2025
beabb1d
Further changes to docs
fbeaudoincoveo Oct 27, 2025
3abc41e
Add generated files
developer-experience-bot[bot] Oct 27, 2025
6180bbe
Merge branch 'main' into KIT-4997
fbeaudoincoveo Oct 27, 2025
f9f1c27
Merge branch 'KIT-4997' into KIT-4974
fbeaudoincoveo Oct 27, 2025
85e0f84
Undo changes in result-wrapper
fbeaudoincoveo Oct 27, 2025
aa181d3
Use wrapInResultList and wrapInResultTemplate helpers
fbeaudoincoveo Oct 27, 2025
d2f9489
Rename variable
fbeaudoincoveo Oct 27, 2025
6273add
Improve docs
fbeaudoincoveo Oct 27, 2025
c4b45a4
Improve docs
fbeaudoincoveo Oct 27, 2025
57a5577
Fix import path
fbeaudoincoveo Oct 27, 2025
c5f9252
Remove cypress tests
fbeaudoincoveo Oct 27, 2025
43fa016
Revert "Remove cypress tests"
fbeaudoincoveo Oct 27, 2025
b90393a
Merge branch 'KIT-4997' into KIT-4974
fbeaudoincoveo Oct 27, 2025
bdf395d
Delete cypress tests
fbeaudoincoveo Oct 27, 2025
c498a33
Undo change
fbeaudoincoveo Oct 27, 2025
aa1bc28
Update packages/atomic/src/components/search/atomic-result-number/ato…
fbeaudoincoveo Nov 3, 2025
b310a54
Update packages/atomic/src/components/search/atomic-result-number/ato…
fbeaudoincoveo Nov 3, 2025
74b2323
Merge branch 'main' into KIT-4974
fbeaudoincoveo Nov 3, 2025
1f2fc09
chore(atomic): move private getter to end of class in atomic-result-n…
Copilot Nov 3, 2025
22f252a
docs: remove invalid @slot tag from light DOM component (#6441)
Copilot Nov 3, 2025
d509729
Reorder imports
fbeaudoincoveo Nov 3, 2025
f52b89d
Merge branch 'KIT-4974' of https://github.com/coveo/ui-kit into KIT-4974
fbeaudoincoveo Nov 3, 2025
7230295
Add generated files
developer-experience-bot[bot] Nov 3, 2025
3582b6b
refactor: remove unnecessary else after throw in atomic-result-number…
Copilot Nov 3, 2025
bec1c72
Fix atomic-result-number stories after @slot removal (#6453)
Copilot Nov 4, 2025
5cc6240
Merge branch 'main' into KIT-4974
fbeaudoincoveo Nov 4, 2025
b501f44
Compose LightDomMixin and InitializeBindingsMixin in atomic-result-nu…
Copilot Nov 4, 2025
f710310
Merge branch 'main' into KIT-4974
fbeaudoincoveo Nov 4, 2025
2785b49
Add generated files
developer-experience-bot[bot] Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 119 additions & 48 deletions .github/prompts/generate-vitest-tests-atomic-lit-components.prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,64 +15,68 @@ Read `../instructions/tests-atomic.instructions.md` before starting.

**Component structure knowledge:**
- Molecules - Integrate with Headless controllers (search-box, facets, pager)
- Result/Product templates - Get data from parent context (`atomic-result`, `atomic-product`)
- Atoms - Basic UI elements (buttons, icons)
- Enzymes - Complex business logic components

**Determine testability:** If component isn't a molecule or doesn't integrate with Headless, this prompt may not apply.
## Result Template Component Detection

## Find Similar Tested Components
**Result template components** (e.g., `atomic-result-*`, `atomic-field-*`, commerce `atomic-product-*`) don't integrate with Headless controllers directly. They:
- Get data from parent context via `createResultContextController` or `createItemContextController`
- May use `ResultTemplatesHelpers.getResultProperty` for field access
- Live in `result-template-components/` or `product-template-components/` directories

**First, find equivalent components in other use cases (search/commerce/insight/recommendations) with existing Lit tests.**
**Fixtures available:**
- Search: `renderInAtomicResult` from `atomic-result-fixture.ts`
- Commerce: `renderInAtomicProduct` from `atomic-product-fixture.ts`

**Example:** Testing `atomic-query-error` (search) β†’ look for `atomic-commerce-query-error/*.spec.ts` (commerce)
**Example usage:** See `atomic-product-price.spec.ts` (commerce) or `atomic-result-number.spec.ts` (search)

**How to identify:**
- Extract base name: `atomic-[use-case-]component-name` β†’ `component-name`
- Search other use case folders for `atomic-*{base-name}*.spec.ts`
- Verify Lit tests: imports from `.ts` (not `.tsx`), uses `renderInAtomic*Interface` helpers

**Analyze similar test file for:**
- `renderComponent` helper structure
- Locator patterns (`page.getByRole`, shadow parts)
- Console mocking strategy (nested describe blocks for errors)
- Controller mocking approach
- Test organization and assertion patterns

**If no similar tests found:** Ask user if they know of one to reference.

**Include pattern discovery as a todo item:**
- [ ] Find and analyze similar tested component in other use cases
**Continue with this prompt if component is a molecule, enzyme, or result/product template component.**

## Analysis Phase

Before writing tests:

1. **Find and analyze similar tested component in other use cases** (see "Find Similar Tested Components" section above)
2. **Verify test fixtures exist** - Check `vitest-utils/testing-helpers/fixtures/headless/{interface}/` for `buildFake{ControllerName}`. If missing, create following pattern from similar fixture (e.g., `summary-controller.ts`):
```typescript
export const defaultState = {...} satisfies ControllerState;
export const defaultImplementation = {
subscribe: genericSubscribe,
state: defaultState,
} satisfies Controller;
export const buildFakeController = ({implementation, state} = {}) => ({
...defaultImplementation,
...implementation,
...(state && {state: {...defaultState, ...state}}),
});
```
1. **Identify component category and find reference tests:**
- **Molecules/enzymes:** Find equivalent in other use cases (search/commerce/insight/recommendations)
- Extract base name: `atomic-[use-case-]component-name` β†’ `component-name`
- Search: `atomic-*{base-name}*.spec.ts` in other use case folders
- Verify Lit tests: imports from `.ts` (not `.tsx`), uses `renderInAtomic*Interface`
- **Result/product templates:** Find similar template component tests
- Check `atomic-product-price.spec.ts`, `atomic-result-number.spec.ts`
- **Analyze reference test for:** render helper structure, locator patterns, mocking strategy, test organization
- **If no similar tests found:** Ask user if they know of one to reference
2. **Verify test fixtures exist:**
- **Molecules/enzymes:** Check `vitest-utils/testing-helpers/fixtures/headless/{interface}/` for `buildFake{ControllerName}`. If missing, create following pattern from similar fixture (e.g., `summary-controller.ts`):
```typescript
export const defaultState = {...} satisfies ControllerState;
export const defaultImplementation = {
subscribe: genericSubscribe,
state: defaultState,
} satisfies Controller;
export const buildFakeController = ({implementation, state} = {}) => ({
...defaultImplementation,
...implementation,
...(state && {state: {...defaultState, ...state}}),
});
```
- **Result/product templates:** Ensure `atomic-result-fixture.ts` or `atomic-product-fixture.ts` exists (already available)
3. Read component implementation
4. Identify public API: properties, methods, events
5. **Verify component type** - Stop if not a molecule/enzyme integrating with Headless
6. Note Headless controller dependencies
7. Check for i18n or custom styling requirements
5. Note dependencies:
- **Molecules/enzymes:** Headless controller dependencies
- **Result/product templates:** Result/product fields accessed, custom events
6. Check for i18n or custom styling requirements
8. **Identify console logging scenarios:**
- `@bindStateToController` decorator (logs errors on missing initialize/controller)
- Parent element requirements (logs errors when rendered outside required parent)
- Prop validation with console warnings
- Deprecated prop usage

## Test File Pattern
## Test File Patterns

### Molecule/Enzyme Pattern

Reference: `packages/atomic/scripts/generate-component-templates/component.spec.ts.hbs`

Expand Down Expand Up @@ -156,11 +160,68 @@ describe('atomic-component', () => {
});
```

### Result/Product Template Pattern

For result/product template components, use context fixtures:

**βœ… DO:**
```typescript
import {type Result, ResultTemplatesHelpers} from '@coveo/headless';
import {html} from 'lit';
import {ifDefined} from 'lit/directives/if-defined.js';
import {describe, expect, it, vi} from 'vitest';
import {renderInAtomicResult} from '@/vitest-utils/testing-helpers/fixtures/atomic/search/atomic-result-fixture';
import {buildFakeSearchEngine} from '@/vitest-utils/testing-helpers/fixtures/headless/search/engine';
import type {AtomicResultNumber} from './atomic-result-number';
import './atomic-result-number';

vi.mock('@coveo/headless', async () => {
const actual = await vi.importActual<typeof import('@coveo/headless')>('@coveo/headless');
return {
...actual,
ResultTemplatesHelpers: {
getResultProperty: vi.fn(),
},
};
});

describe('atomic-result-number', () => {
const mockedEngine = buildFakeSearchEngine();
const mockResult: Partial<Result> = {
raw: {size: 1024} as Result['raw'],
};

const renderComponent = async ({
props = {},
result = mockResult,
}: {
props?: Partial<{field: string}>;
result?: Partial<Result>;
} = {}) => {
const {element} = await renderInAtomicResult<AtomicResultNumber>({
template: html`<atomic-result-number field=${ifDefined(props.field)}></atomic-result-number>`,
selector: 'atomic-result-number',
result: result as Result,
bindings: (bindings) => {
bindings.engine = mockedEngine;
return bindings;
},
});
return {element};
};

// Tests...
});
```

**Note:** Commerce components use `renderInAtomicProduct` with `product` prop instead of `result`.

**Key patterns from actual codebase:**
- Return `{element, locators, parts}` from render function for clean test access
- Use `page.getByRole()` for semantic locators
- Define `parts()` function for shadow DOM queries
- Mock headless with `vi.mock('@coveo/headless', {spy: true})`
- Mock headless controllers with `vi.mock('@coveo/headless', {spy: true})`
- Mock `ResultTemplatesHelpers` with partial import for result/product templates
- Use `ifDefined()` for optional props/content

## Critical Patterns
Expand Down Expand Up @@ -198,6 +259,11 @@ it('should render button when enabled', async () => {
const {parts} = await renderComponent({enabled: true});
await expect.element(parts.button).toBeInTheDocument();
});

// Test components that self-remove on error/null
const {atomicResult} = await renderComponent({props: {field: 'nonexistent'}});
const element = atomicResult.querySelector('atomic-result-number');
expect(element).toBeNull(); // Component removed itself
```

**❌ DON'T:**
Expand All @@ -219,26 +285,35 @@ it('should render all parts', async () => {
// When some parts are conditional, split into separate tests
});

// Don't manually create controller mocks
// Don't manually create controller mocks - use buildFake* helpers
const mockController = {state: {}, subscribe: vi.fn()};

// Don't test error properties on components that self-remove
const {element} = await renderComponent({/* triggers removal */});
expect(element.error).toBe(...); // Element is null, can't access properties
```

## Test Coverage Checklist

**Pattern Analysis:**
- [ ] Found and analyzed similar component's test file in other use case
- [ ] Identified render helper patterns from similar component
- [ ] Noted locator/assertion patterns from similar component
- [ ] Found and analyzed reference component's test file (similar component in other use case or equivalent template component)

**Properties:**
- [ ] Valid props β†’ no error
- [ ] Invalid props β†’ error with specific message

**Controller Integration:**
**Controller Integration (Molecules/Enzymes):**
- [ ] Controller built with engine
- [ ] State bound via `@bindStateToController`
- [ ] Methods called on user interaction

**Result/Product Template Components:**
- [ ] Mock `ResultTemplatesHelpers.getResultProperty` for field access
- [ ] Test with valid result/product data
- [ ] Test field value parsing (if applicable)
- [ ] Test self-removal behavior for null/invalid values (if applicable)
- [ ] Test custom event handling (if component dispatches/listens)

**Rendering:**
- [ ] Shadow parts present/conditional
- [ ] Slotted content
Expand All @@ -251,7 +326,3 @@ const mockController = {state: {}, subscribe: vi.fn()};
## Post-Execution Summary

Generate execution summary at `.github/prompts/.executions/generate-vitest-tests-[component]-[YYYY-MM-DD-HHmmss].prompt-execution.md` following `TEMPLATE.prompt-execution.md`. Include reference component used, issues encountered, ambiguities requiring interpretation, and concrete improvement suggestions. Inform user of summary location.


````
```
64 changes: 51 additions & 13 deletions .github/prompts/migrate-stencil-to-lit.prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,42 @@ Migrate files according to this mapping:
- Convert lifecycle methods (componentWillLoad β†’ willUpdate, etc.)
- Replace CSS classes with Tailwind CSS utilities
- **Use Lit reactive controllers instead of Stencil context providers** (e.g., ProductContext should be a reactive controller)
- **Result template components:** Replace Stencil `@ResultContext()` decorator with `createResultContextController`:
```typescript
import {createResultContextController} from '@/src/components/search/result-template-component-utils/context/result-context-controller';

private resultContext = createResultContextController(this);
private get result(): Result {
return this.resultContext.item as Result;
}
```
- **Use Lit's `nothing` directive instead of `null` for conditional rendering**

**Light DOM Components:**

Light DOM components render without Shadow DOM for styling integration. Use `LightDomMixin` for this pattern.

```typescript
import {LightDomMixin} from '@/src/mixins/light-dom';

// Basic light DOM component
@customElement('atomic-result-number')
@bindings()
export class AtomicResultNumber
extends LightDomMixin(LitElement)
implements InitializableComponent<Bindings>

// Light DOM component requiring bindings initialization
@customElement('atomic-icon')
export class AtomicIcon
extends LightDomMixin(InitializeBindingsMixin(LitElement))
implements InitializableComponent<AnyBindings>
```

**When to use:**
- `LightDomMixin(LitElement)` - Most light DOM components with `@bindings()` decorator
- `LightDomMixin(InitializeBindingsMixin(LitElement))` - Components needing binding initialization logic (e.g., components without use case-specific bindings)

**Import Path Migration (CRITICAL):**

**Rule:** Replace ALL `../` imports with `@/src/` path aliases.
Expand Down Expand Up @@ -330,21 +364,27 @@ return condition ? html`<div>Content</div>` : nothing;
html`<div>${shouldShow ? html`<span>Content</span>` : nothing}</div>`;
```

## Important Constraints
**❌ Missing result context controller:**

**Do not do the following unless explicitly asked by the user:**
```typescript
// DON'T: Try to access result without controller
@ResultContext() result!: Result; // Stencil pattern
```

**βœ… Correct result context setup:**

```typescript
import {createResultContextController} from '@/src/components/search/result-template-component-utils/context/result-context-controller';

- Do not build the Atomic package
- Do not run tests or generate new tests
- Do not fix linting issues (save linting fixes for after migration is complete)
- Do not modify existing test files (`.spec.ts`, `e2e/` files)
- Do not check if generation scripts succeeded or look for generated files
private resultContext = createResultContextController(this);
private get result(): Result {
return this.resultContext.item as Result;
}
```

**Focus only on:**
## Important Constraints

- Code migration from Stencil to Lit
- Style migration from PostCSS to Tailwind
- Functional component/utility migration
Focus on code/style/functional migration only. Do not: build, test, lint, modify test files, or verify generation script outputs (unless user requests).

## Migration Checklist

Expand Down Expand Up @@ -404,5 +444,3 @@ After completing migration, generate execution summary:
**4. Inform user** about summary location

**5. Mark complete** only after file created and user informed.

```
Loading
Loading