diff --git a/libs/portal-integration-angular/src/lib/core/components/ocx-content-container/ocx-content-container.component.spec.ts b/libs/portal-integration-angular/src/lib/core/components/ocx-content-container/ocx-content-container.component.spec.ts
index f80d9e18..f2048462 100644
--- a/libs/portal-integration-angular/src/lib/core/components/ocx-content-container/ocx-content-container.component.spec.ts
+++ b/libs/portal-integration-angular/src/lib/core/components/ocx-content-container/ocx-content-container.component.spec.ts
@@ -1,88 +1,50 @@
+import { OcxContentContainerHarness } from './../../../../../testing/ocx-content-container.harness'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { OcxContentContainerComponent } from './ocx-content-container.component'
import { OcxContentContainerDirective } from '../../directives/ocx-content-container.directive'
-import { Component } from '@angular/core'
-
-// Mock host component that's used in all tests that require a dynamic layout change
-// Using this mock host allows us to simulate Angular @Input mechanisms
-@Component({
- template: `
-
- `,
-})
-class TestHostComponent {
- layout: 'horizontal' | 'vertical' = 'horizontal';
- breakpoint: 'sm' | 'md' | 'lg' | 'xl' = 'md'
-}
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'
describe('OcxContentContainerComponent', () => {
- let component: TestHostComponent | OcxContentContainerComponent
- let fixture: ComponentFixture
+ let component: OcxContentContainerComponent
+ let fixture: ComponentFixture
+ let ocxContentContainerHarness: OcxContentContainerHarness
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [OcxContentContainerComponent, OcxContentContainerDirective, TestHostComponent],
+ declarations: [OcxContentContainerComponent, OcxContentContainerDirective],
}).compileComponents()
fixture = TestBed.createComponent(OcxContentContainerComponent)
component = fixture.componentInstance
- fixture.detectChanges()
+ ocxContentContainerHarness = await TestbedHarnessEnvironment.harnessForFixture(fixture, OcxContentContainerHarness)
})
it('should create', () => {
expect(component).toBeTruthy()
})
- it('should render a horizontal layout container with all expected css classes', () => {
- // Check that layout is horizontal by default
- expect(component.layout).toEqual('horizontal')
- // Check that breakpoint is md by default
- expect(component.breakpoint).toEqual('md')
- fixture.detectChanges()
-
- // Check that the classList of the rendered element contains all expected classes
+ it('should render a horizontal layout container with md breakpoint by default', async () => {
const expectedClasses = ['flex', 'py-3', 'gap-3', 'flex-column', 'md:flex-row']
- expect(Object.keys(fixture.debugElement.children[0].classes)).toEqual(expectedClasses)
+ expect(await ocxContentContainerHarness.getLayoutClasses()).toEqual(expectedClasses)
+ expect(await ocxContentContainerHarness.getLayout()).toEqual('horizontal')
+ expect(await ocxContentContainerHarness.getBreakpoint()).toEqual('md')
})
- it('should render a horizontal layout container with all expected css classes and a specified breakpoint', () => {
- // Check that layout is horizontal by default
- expect(component.layout).toEqual('horizontal')
- // Check that breakpoint is md by default
- expect(component.breakpoint).toEqual('md')
- fixture.detectChanges()
-
- // Check that the classList of the rendered element contains all expected classes
- const expectedClassesMD = ['flex', 'py-3', 'gap-3', 'flex-column', 'md:flex-row']
- expect(Object.keys(fixture.debugElement.children[0].classes)).toEqual(expectedClassesMD)
-
- component.breakpoint = "lg"
- fixture.detectChanges()
+ it('should render a horizontal layout container while respecting a specified breakpoint', async () => {
+ component.breakpoint = 'lg'
- // Check that breakpoint is now lg and that classes have been updated accordingly
- expect(component.breakpoint).toEqual('lg')
- const expectedClassesLG = ['flex', 'py-3', 'gap-3', 'flex-column', 'lg:flex-row']
- expect(Object.keys(fixture.debugElement.children[0].classes)).toEqual(expectedClassesLG)
+ const expectedClassesLG = ['flex', 'py-3', 'gap-3', 'flex-column', 'lg:flex-row']
+ expect(await ocxContentContainerHarness.getLayoutClasses()).toEqual(expectedClassesLG)
+ expect(await ocxContentContainerHarness.getLayout()).toEqual('horizontal')
+ expect(await ocxContentContainerHarness.getBreakpoint()).toEqual('lg')
})
- it('should render a vertical layout container with all expected css classes', () => {
- // Replace default component with custom host component to simulate input behavior
- fixture = TestBed.createComponent(TestHostComponent)
- component = fixture.componentInstance
- fixture.detectChanges()
-
- // Check that layout is horizontal by default
- expect(component.layout).toEqual('horizontal')
-
- // Set layout to 'vertical'
+ it('should render a vertical layout container if specified', async () => {
component.layout = 'vertical'
- fixture.detectChanges()
-
- // Check that layout is now vertical
- expect(component.layout).toEqual('vertical')
- // Check that the classList of the rendered element contains all expected classes
- const expectedClasses = ["flex", "py-3", "gap-3", "flex-column"]
- expect(Object.keys(fixture.debugElement.children[0].children[0].classes)).toEqual(expectedClasses)
+ const expectedClasses = ['flex', 'py-3', 'gap-3', 'flex-column']
+ expect(await ocxContentContainerHarness.getLayoutClasses()).toEqual(expectedClasses)
+ expect(await ocxContentContainerHarness.getLayout()).toEqual('vertical')
+ expect(await ocxContentContainerHarness.getBreakpoint()).toBeUndefined()
})
})
diff --git a/libs/portal-integration-angular/src/lib/core/components/ocx-content/ocx-content.component.spec.ts b/libs/portal-integration-angular/src/lib/core/components/ocx-content/ocx-content.component.spec.ts
index f736deb6..88052ee9 100644
--- a/libs/portal-integration-angular/src/lib/core/components/ocx-content/ocx-content.component.spec.ts
+++ b/libs/portal-integration-angular/src/lib/core/components/ocx-content/ocx-content.component.spec.ts
@@ -1,79 +1,45 @@
+import { OcxContentHarness } from './../../../../../testing/ocx-content.harness';
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { OcxContentComponent } from './ocx-content.component'
-import { Component } from '@angular/core'
import { OcxContentDirective } from '../../directives/ocx-content.directive'
-import { By } from '@angular/platform-browser'
-
-// Mock host component that's used in all tests that require a dynamic ocxContent title change
-// Using this mock host allows us to simulate Angular @Input mechanisms
-@Component({
- template: ` `,
-})
-class TestHostComponent {
- title = ''
-}
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
describe('OcxContentComponent', () => {
- let component: TestHostComponent | OcxContentComponent
- let fixture: ComponentFixture
- const titleElemID = 'ocxContentTitleElement'
+ let component: OcxContentComponent
+ let fixture: ComponentFixture
+ let ocxContentHarness: OcxContentHarness
const testComponentTitle = 'My cool title'
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [OcxContentComponent, OcxContentDirective, TestHostComponent],
+ declarations: [OcxContentComponent, OcxContentDirective],
}).compileComponents()
fixture = TestBed.createComponent(OcxContentComponent)
component = fixture.componentInstance
- fixture.detectChanges()
+ ocxContentHarness = await TestbedHarnessEnvironment.harnessForFixture(fixture, OcxContentHarness)
})
it('should create', () => {
expect(component).toBeTruthy()
})
- it('should render a ocxContent card with no title by default', () => {
- // Check that the title is falsy (in this case '') by default
- expect(component.title).toBeFalsy()
- fixture.detectChanges()
-
- // Check that classList of element contains all expected classes
+ it('should render a ocxContent card with no title by default', async () => {
const expectedClasses = ['card']
- expect(Object.keys(fixture.debugElement.children[0].classes)).toEqual(expectedClasses)
-
- // Check that title element doesn't exist inside of ocxContent card
- expect(fixture.debugElement.query(By.css(`#${titleElemID}`))).toBeFalsy()
+ expect(await ocxContentHarness.getContentClasses()).toEqual(expectedClasses)
+ expect(await ocxContentHarness.hasTitle()).toEqual(false)
})
- it('should render a ocxContent card with a title, when given a title via input', () => {
- // Replace default component with custom host component to simulate input behavior
- fixture = TestBed.createComponent(TestHostComponent)
- component = fixture.componentInstance
- fixture.detectChanges()
-
- // Check that initial rendering without title still works as expected
- // Check that the title is falsy (in this case '') by default
- expect(component.title).toBeFalsy()
- fixture.detectChanges()
-
- // Check that classList of element contains all expected classes
+ it('should render a ocxContent card with a title, when given a title via input', async () => {
const expectedClasses = ['card']
- expect(Object.keys(fixture.debugElement.children[0].children[0].classes)).toEqual(expectedClasses)
+ expect(await ocxContentHarness.getContentClasses()).toEqual(expectedClasses)
+ expect(await ocxContentHarness.hasTitle()).toEqual(false)
- // Check that title element doesn't exist inside of ocxContent card
- expect(fixture.debugElement.query(By.css(`#${titleElemID}`))).toBeFalsy()
-
- // Set title to a specific value
component.title = testComponentTitle
- fixture.detectChanges()
-
- // Check that title now matches the expected value
- expect(component.title).toEqual(testComponentTitle)
- // Check that title element has been rendered and contains the expected text content
- const titleElement = fixture.debugElement.query(By.css(`#${titleElemID}`))
- expect(titleElement).toBeTruthy()
- expect(titleElement.nativeElement.textContent).toEqual(testComponentTitle)
+ const expectedTitleClasses = ['font-medium', 'text-lg']
+ expect(await ocxContentHarness.hasTitle()).toEqual(true)
+ expect(await ocxContentHarness.getTitle()).toEqual(testComponentTitle)
+ expect(await ocxContentHarness.getTitleClasses()).toEqual(expectedTitleClasses)
})
})
diff --git a/libs/portal-integration-angular/testing/div.harness.ts b/libs/portal-integration-angular/testing/div.harness.ts
index 45a66e68..39669eae 100644
--- a/libs/portal-integration-angular/testing/div.harness.ts
+++ b/libs/portal-integration-angular/testing/div.harness.ts
@@ -24,4 +24,13 @@ export class DivHarness extends ComponentHarness {
async getText(): Promise {
return await (await this.host()).text()
}
+
+ async getClassList() {
+ const host = await this.host()
+ const attributeString = await host.getAttribute("class");
+ if(attributeString) {
+ return attributeString.trim().split(" ")
+ }
+ return []
+ }
}
diff --git a/libs/portal-integration-angular/testing/ocx-content-container.harness.ts b/libs/portal-integration-angular/testing/ocx-content-container.harness.ts
new file mode 100644
index 00000000..e9944d17
--- /dev/null
+++ b/libs/portal-integration-angular/testing/ocx-content-container.harness.ts
@@ -0,0 +1,25 @@
+import { ComponentHarness } from '@angular/cdk/testing'
+import { DivHarness } from './div.harness';
+
+
+export class OcxContentContainerHarness extends ComponentHarness {
+ static hostSelector = 'ocx-content-container'
+
+ async getLayoutClasses() {
+ const div = await this.locatorFor(DivHarness)()
+ const actualClassList = await div.getClassList()
+
+ return actualClassList;
+ }
+
+ async getLayout(): Promise<'horizontal' | 'vertical'> {
+ const layoutClassses = await this.getLayoutClasses();
+ return layoutClassses.find((c) => c.endsWith(':flex-row')) ? 'horizontal' : 'vertical'
+ }
+
+ async getBreakpoint(): Promise<'sm' | 'md' | 'lg' | 'xl' | undefined> {
+ const layoutClassses = await this.getLayoutClasses();
+ const layoutClass = layoutClassses.find((c) => c.endsWith(':flex-row'))
+ return layoutClass?.split(":")[0] as 'sm' | 'md' | 'lg' | 'xl' | undefined
+ }
+}
diff --git a/libs/portal-integration-angular/testing/ocx-content.harness.ts b/libs/portal-integration-angular/testing/ocx-content.harness.ts
new file mode 100644
index 00000000..03a05f20
--- /dev/null
+++ b/libs/portal-integration-angular/testing/ocx-content.harness.ts
@@ -0,0 +1,42 @@
+import { ComponentHarness } from '@angular/cdk/testing'
+import { DivHarness } from './div.harness'
+import { PHarness } from './p.harness'
+
+export class OcxContentHarness extends ComponentHarness {
+ static hostSelector = 'ocx-content'
+
+ async getContentClasses() {
+ const div = await this.locatorFor(DivHarness)()
+ const actualClassList = await div.getClassList()
+
+ return actualClassList
+ }
+
+ async getTitleClasses() {
+ const p = await this.getTitleHarness()
+ if (p) {
+ const actualClassList = await p.getClassList()
+ return actualClassList
+ }
+ return null
+ }
+
+ async getTitle() {
+ const p = await this.getTitleHarness()
+ if (p) {
+ const titleContent = await p.getText()
+ return titleContent
+ }
+ return null
+ }
+
+ async getTitleHarness() {
+ const pHarness = await this.locatorForOptional(PHarness.with({ id: 'ocxContentTitleElement' }))()
+ return pHarness
+ }
+
+ async hasTitle(): Promise {
+ const title = await this.getTitleHarness()
+ return !!title
+ }
+}
diff --git a/libs/portal-integration-angular/testing/p.harness.ts b/libs/portal-integration-angular/testing/p.harness.ts
new file mode 100644
index 00000000..fbe7fc91
--- /dev/null
+++ b/libs/portal-integration-angular/testing/p.harness.ts
@@ -0,0 +1,41 @@
+import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } from '@angular/cdk/testing'
+
+export interface PHarnessFilters extends BaseHarnessFilters {
+ class?: string
+ id?: string
+}
+
+export class PHarness extends ComponentHarness {
+ static hostSelector = 'p'
+
+ static with(options: PHarnessFilters): HarnessPredicate {
+ return new HarnessPredicate(PHarness, options)
+ .addOption('class', options.class, (harness, c) => HarnessPredicate.stringMatches(harness.getByClass(c), c))
+ .addOption('id', options.id, (harness, id) => HarnessPredicate.stringMatches(harness.hasId(id), id))
+ }
+
+ async getByClass(c: string): Promise {
+ return (await (await this.host()).hasClass(c)) ? c : ''
+ }
+
+ async hasId(id: string): Promise {
+ return (await (await this.host()).matchesSelector('#' + id)) ? id : ''
+ }
+
+ async checkHasClass(value: string) {
+ return await (await this.host()).hasClass(value)
+ }
+
+ async getText(): Promise {
+ return await (await this.host()).text()
+ }
+
+ async getClassList() {
+ const host = await this.host()
+ const attributeString = await host.getAttribute('class')
+ if (attributeString) {
+ return attributeString.trim().split(' ')
+ }
+ return []
+ }
+}