Skip to content

#87 - testing-fab#88

Open
mumenthalers wants to merge 7 commits into
mainfrom
#87-testing-fab
Open

#87 - testing-fab#88
mumenthalers wants to merge 7 commits into
mainfrom
#87-testing-fab

Conversation

@mumenthalers

@mumenthalers mumenthalers commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Implements a configurable Testing FAB in @shiftcode/ngx-components instead of only documenting terminology.

Changes Made

  • Added TestingFabComponent as a floating, always-on-top FAB with an expandable control panel.
  • Added provideTestingFab(...) for opt-in provisioning.
  • Added typed widget contracts for:
    • Action widgets
    • Select query param widgets
    • Custom component widgets
  • Implemented URL-authoritative behavior for select-query-param widgets (read/update query params).
  • Exported the new Testing FAB APIs via libs/components/src/public-api.ts.
  • Added focused unit tests for rendering and behavior.
  • Updated component docs and corrected glossary acronym capitalization (URL, HTML) in CONTEXT.md.
  • Updated provideTestingFab(...) to accept either a static widget config or a factory (ValueOrFactory pattern).
  • Added environment initialization to mount sc-testing-fab automatically via createComponent(...) and provideEnvironmentInitializer(...).
  • Simplified custom-component widgets to render only the component type (removed custom inputs support).
  • Added hardReload support for select-query-param widgets to optionally update the URL and reload directly.
  • Migrated template control flow to modern Angular syntax (@for, @switch, @let) and switched toggle behavior to native popover.
  • Added CSS custom properties for FAB positioning and theming (inset, margin, size, border-radius, background/foreground colors, and icon URL with default Shiftcode logo).
  • Added/updated unit tests to cover provider config modes and hard-reload behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 3, 2026 19:17
@mumenthalers

Copy link
Copy Markdown
Contributor Author

@copilot implement issue #87

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds project terminology definitions for the planned “Testing FAB” feature so Consumer applications and the Library share consistent language when documenting/implementing the FAB and its widgets.

Changes:

  • Introduces standardized terms: Testing FAB, Action Widget, Select Query Param Widget, Custom Component Widget.
  • Documents behavioral concepts (URL-authoritative selection, opt-in provisioning, Consumer-owned activation safety).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CONTEXT.md Outdated
Comment thread CONTEXT.md Outdated
Comment thread CONTEXT.md

Copilot AI commented Jul 3, 2026

Copy link
Copy Markdown

@copilot implement issue #87

Implemented issue #87 in commit b9b7512: added a configurable Testing FAB with provider API (provideTestingFab), action/select-query-param/custom-component widgets, component rendering/URL query-param behavior, tests, and public/docs exports.

@mumenthalers mumenthalers left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot fix comments. make use of the mcp to get info

import { TESTING_FAB_WIDGETS } from './testing-fab-config.token'
import { TestingFabWidget } from './testing-fab-widget.type'

export function provideTestingFab(widgets: readonly TestingFabWidget[]): EnvironmentProviders {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should accept a static config OR one that can be a provider itself (ValueOrFactory as in withCloudWatchLogV2Transport)

export interface TestingFabCustomComponentWidget extends TestingFabWidgetBase {
type: 'custom-component'
component: Type<unknown>
inputs?: Record<string, unknown>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

skip inputs just the component

Comment thread libs/components/src/lib/testing-fab/testing-fab.component.scss
Comment on lines +31 to +32
<section *ngIf="isOpen()" class="sc-testing-fab__panel">
<ng-container *ngFor="let widget of widgets; trackBy: trackById">

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use new angular control flow @if and @for and so on. no more using the directives

🧪
</button>

<section *ngIf="isOpen()" class="sc-testing-fab__panel">

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use a native popover (ask mdn) with nice css only animations and toggle action triggered without JS

Comment on lines +80 to +82
protected runAction(widget: TestingFabActionWidget) {
widget.action()
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call directly .action instead of wrapping it here in an extra func

Comment on lines +90 to +98
protected setQueryParam(widget: TestingFabSelectQueryParamWidget, event: Event) {
const nextValue = (event.target as HTMLSelectElement).value
void this.router.navigate([], {
queryParams: {
[widget.queryParam]: nextValue || null,
},
queryParamsHandling: 'merge',
})
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

most cases i can think of will require a hard reload afterwards. add it as option (whether it's needed). when it is, do the reload direxctly to the url with the param withou using angular first

})
}

protected trackById(_index: number, widget: TestingFabWidget): string {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mthod unused when sing modern control flow

Comment on lines +104 to +114
protected asActionWidget(widget: TestingFabWidget): TestingFabActionWidget | null {
return widget.type === 'action' ? widget : null
}

protected asSelectWidget(widget: TestingFabWidget): TestingFabSelectQueryParamWidget | null {
return widget.type === 'select-query-param' ? widget : null
}

protected asCustomComponentWidget(widget: TestingFabWidget): TestingFabCustomComponentWidget | null {
return widget.type === 'custom-component' ? widget : null
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

angalr select control flow can do proper type narrowing when sing the modern @switch

import { TestingFabWidget } from './testing-fab-widget.type'

export function provideTestingFab(widgets: readonly TestingFabWidget[]): EnvironmentProviders {
return makeEnvironmentProviders([{ provide: TESTING_FAB_WIDGETS, useValue: widgets }])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how will the component be rendered?

do it like this:

Suggested change
return makeEnvironmentProviders([{ provide: TESTING_FAB_WIDGETS, useValue: widgets }])
return makeEnvironmentProviders([
{ provide: TESTING_FAB_WIDGETS, useValue: widgets },
provideEnvironmentInitializer(() => initializerTestingFab())
])

where initializerTestingFab looks like

export function initializeDataSourceSwitcher() {
  const doc = inject(DOCUMENT)
  const appRef = inject(ApplicationRef)
  const envInjector = inject(EnvironmentInjector)

  const host = doc.createElement('sc-testing-fab')
  const cmpRef = createComponent(TestingFabComponent, {
    hostElement: host,
    environmentInjector: envInjector,
  })

  appRef.attachView(cmpRef.hostView)
  doc.body.appendChild(host)
}

Copilot AI commented Jul 3, 2026

Copy link
Copy Markdown

@copilot fix comments. make use of the mcp to get info

Addressed in commit 51137d0.

I updated the Testing FAB provider API and rendering initializer, migrated the component to modern Angular control flow + native popover, added hard-reload support for select query-param widgets, removed custom-component inputs, and updated tests accordingly. I also attempted to fetch PR metadata via GitHub MCP, but this environment returned 404 for shiftcode/sc-ng-commons-public PR #87.

Comment thread libs/components/src/lib/testing-fab/provide-testing-fab.ts Outdated
Comment thread libs/components/src/lib/testing-fab/testing-fab.component.ts Outdated
@mumenthalers

Copy link
Copy Markdown
Contributor Author

@copilot fix fox

Copilot AI commented Jul 3, 2026

Copy link
Copy Markdown

@copilot fix fox

Fixed in commit 3b41721.

@mumenthalers

Copy link
Copy Markdown
Contributor Author

@copilot fix formatting (prettier). also make sure lint, test, build will run

Copilot AI commented Jul 3, 2026

Copy link
Copy Markdown

@copilot fix formatting (prettier). also make sure lint, test, build will run

Addressed in commit d9d98ac.

I applied Prettier formatting fixes to the 4 failing Testing FAB files. I also checked Actions via MCP: the new workflow run for this commit is #515 and is currently action_required, so lint/test/build have not executed yet until that run is approved/released.

@mumenthalers

Copy link
Copy Markdown
Contributor Author

@copilot now linting failed. you know that you can execute those commands yourself?

and when commitin it should actually be run by husky, right?

Copilot AI commented Jul 3, 2026

Copy link
Copy Markdown

@copilot now linting failed. you know that you can execute those commands yourself?

and when commitin it should actually be run by husky, right?

Fixed in commit d243942.

I checked the failing CI lint job via MCP logs, reproduced the issue context locally as far as this sandbox allows, and fixed the reported lint violations in the Testing FAB files.

And yes: commits should run Husky pre-commit here (.husky/pre-commit runs npx lint-staged), so staged files in libs/components go through eslint/prettier before commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants