Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sitecore-jss-angular] fix placeholder guards #1706

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Component, DebugElement, EventEmitter, Input, Output } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ComponentRendering } from '@sitecore-jss/sitecore-jss/layout';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { ComponentRendering } from '@sitecore-jss/sitecore-jss/layout';

import { JssModule } from '../lib.module';

Expand Down Expand Up @@ -104,119 +104,113 @@ describe('<sc-placeholder />', () => {
{ label: 'LayoutService data - EE on', data: eeData },
];

// eslint-disable-next-line @typescript-eslint/no-explicit-any
testData.forEach((dataSet: any) => {
testData.forEach((dataSet) => {
describe(`with ${dataSet.label}`, () => {
it(
'should render a placeholder with given key',
waitForAsync(() => {
const component = dataSet.data.sitecore.route.placeholders.main.find(
(c: ComponentRendering) => c.componentName
);
waitForAsync(async () => {
const component = (dataSet.data.sitecore.route.placeholders
.main as ComponentRendering[]).find((c) => c.componentName);
const phKey = 'page-content';
comp.name = phKey;
comp.rendering = component;
comp.rendering = component!;
fixture.detectChanges();

fixture.whenStable().then(() => {
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();

const downloadCallout = de.query(By.directive(TestDownloadCalloutComponent));
expect(downloadCallout).not.toBeNull();
expect(downloadCallout.nativeElement.innerHTML).toContain('Download');
const downloadCallout = de.query(By.directive(TestDownloadCalloutComponent));
expect(downloadCallout).not.toBeNull();
expect(downloadCallout.nativeElement.innerHTML).toContain('Download');

const img = de.nativeElement.getElementsByTagName('img')[0];
expect(img).not.toBeDefined();
});
const img = de.nativeElement.getElementsByTagName('img')[0];
expect(img).not.toBeDefined();
})
);

it(
'should render nested placeholders',
waitForAsync(() => {
waitForAsync(async () => {
const component = dataSet.data.sitecore.route;
const phKey = 'main';
comp.name = phKey;
comp.rendering = component;
comp.rendering = (component as unknown) as ComponentRendering;
fixture.detectChanges();

// because nested placeholders result in additional async loading _after_ whenStable,
// we have to check for stability AGAIN internally
fixture.whenStable().then(() => {
fixture.detectChanges();

fixture.whenStable().then(() => {
fixture.detectChanges();
const downloadCallout = de.query(By.directive(TestDownloadCalloutComponent));
expect(downloadCallout).not.toBeNull();
expect(downloadCallout.nativeElement.innerHTML).toContain('Download');
});
});
await fixture.whenStable();
fixture.detectChanges();

await fixture.whenStable();
fixture.detectChanges();

const downloadCallout = de.query(By.directive(TestDownloadCalloutComponent));
expect(downloadCallout).not.toBeNull();
expect(downloadCallout.nativeElement.innerHTML).toContain('Download');
})
);
});
});

it(
'should populate the "key" attribute of placeholder chrome',
waitForAsync(() => {
waitForAsync(async () => {
const component = eeData.sitecore.route;
const phKey = 'main';

comp.name = phKey;
comp.rendering = (component as unknown) as ComponentRendering;
fixture.detectChanges();

fixture.whenStable().then(() => {
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();

const eeChrome = de.nativeElement.querySelector(
`[chrometype="placeholder"][kind="open"][id="${phKey}"]`
);
expect(eeChrome).not.toBeNull();
const eeChrome = de.nativeElement.querySelector(
`[chrometype="placeholder"][kind="open"][id="${phKey}"]`
);
expect(eeChrome).not.toBeNull();

const keyAttribute = eeChrome.getAttribute('key');
expect(keyAttribute).toBeDefined();
expect(keyAttribute).toBe(phKey);
});
const keyAttribute = eeChrome.getAttribute('key');
expect(keyAttribute).toBeDefined();
expect(keyAttribute).toBe(phKey);
})
);

it(
'should copy parent style attribute',
waitForAsync(() => {
waitForAsync(async () => {
const component = nonEeDevData.sitecore.route;
const phKey = 'main';
comp.name = phKey;
comp.rendering = (component as unknown) as ComponentRendering;
fixture.detectChanges();

fixture.whenStable().then(() => {
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();

// let's grab the style name from the parent
let parentKey = '';
const homeComp = de.query(By.directive(TestHomeComponent));
const homeAttributes = homeComp.nativeElement.attributes;
if (homeAttributes.length) {
const parentAttribute = homeComp.nativeElement.attributes.item(0).name;
parentKey = parentAttribute.replace('_nghost-', '');
}
// let's grab the style name from the parent
let parentKey = '';
const homeComp = de.query(By.directive(TestHomeComponent));
const homeAttributes = homeComp.nativeElement.attributes;
if (homeAttributes.length) {
const parentAttribute = homeComp.nativeElement.attributes.item(0).name;
parentKey = parentAttribute.replace('_nghost-', '');
}

fixture.whenStable().then(() => {
fixture.detectChanges();
const downloadCallout = de.query(By.directive(TestDownloadCalloutComponent));
expect(downloadCallout.nativeElement.attributes.item(0).name).toEqual(
`_ngcontent-${parentKey}`
);
});
});
await fixture.whenStable();
fixture.detectChanges();

const downloadCallout = de.query(By.directive(TestDownloadCalloutComponent));
expect(downloadCallout.nativeElement.attributes.item(0).name).toEqual(
`_ngcontent-${parentKey}`
);
})
);

it(
'should skip rendering unknown components',
waitForAsync(() => {
waitForAsync(async () => {
const phKey = 'main';
const route = {
placeholders: {
Expand All @@ -235,20 +229,19 @@ describe('<sc-placeholder />', () => {
comp.rendering = (route as unknown) as ComponentRendering;
fixture.detectChanges();

fixture.whenStable().then(() => {
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();

expect(de.children.length).toBe(1);
expect(de.children.length).toBe(1);

const homeDiv = de.query(By.directive(TestHomeComponent));
expect(homeDiv).not.toBeNull();
});
const homeDiv = de.query(By.directive(TestHomeComponent));
expect(homeDiv).not.toBeNull();
})
);

it(
'should skip rendering components with no name',
waitForAsync(() => {
waitForAsync(async () => {
const phKey = 'main';
const route = {
placeholders: {
Expand All @@ -267,20 +260,19 @@ describe('<sc-placeholder />', () => {
comp.rendering = (route as unknown) as ComponentRendering;
fixture.detectChanges();

fixture.whenStable().then(() => {
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();

expect(de.children.length).toBe(1);
expect(de.children.length).toBe(1);

const homeDiv = de.query(By.directive(TestHomeComponent));
expect(homeDiv).not.toBeNull();
});
const homeDiv = de.query(By.directive(TestHomeComponent));
expect(homeDiv).not.toBeNull();
})
);

it(
'should render null for unknown placeholder',
waitForAsync(() => {
waitForAsync(async () => {
const phKey = 'unknown';
const route = {
placeholders: {
Expand All @@ -296,12 +288,11 @@ describe('<sc-placeholder />', () => {
comp.rendering = (route as unknown) as ComponentRendering;
fixture.detectChanges();

fixture.whenStable().then(() => {
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();

const element = de.query(By.css('sc-placeholder')).nativeElement;
expect(element.children.length).toBe(0);
});
const element = de.query(By.css('sc-placeholder')).nativeElement;
expect(element.children.length).toBe(0);
})
);
});
Expand Down Expand Up @@ -381,7 +372,7 @@ describe('<sc-placeholder /> with input/output binding', () => {

it(
'should bind inputs to children',
waitForAsync(() => {
waitForAsync(async () => {
const expectedMessage = 'lorem';
const functionResult = 42;
const changedMessage = 'ipsum';
Expand All @@ -399,21 +390,21 @@ describe('<sc-placeholder /> with input/output binding', () => {
comp.childMessage = expectedMessage;
fixture.detectChanges();

fixture.whenStable().then(() => {
fixture.detectChanges();
const childComponent = de.query(By.directive(TestChildComponent));
expect(childComponent.nativeElement.innerHTML).toContain(expectedMessage);
expect(childComponent.nativeElement.innerHTML).toContain(functionResult);
comp.childMessage = changedMessage;
fixture.detectChanges();
expect(childComponent.nativeElement.innerHTML).toContain(changedMessage);
});
await fixture.whenStable();
fixture.detectChanges();

const childComponent = de.query(By.directive(TestChildComponent));
expect(childComponent.nativeElement.innerHTML).toContain(expectedMessage);
expect(childComponent.nativeElement.innerHTML).toContain(functionResult);
comp.childMessage = changedMessage;
fixture.detectChanges();
expect(childComponent.nativeElement.innerHTML).toContain(changedMessage);
})
);

it(
'should bind inputs to multiple',
waitForAsync(() => {
waitForAsync(async () => {
const expectedMessage = 'lorem';

comp.rendering = ({
Expand All @@ -435,20 +426,20 @@ describe('<sc-placeholder /> with input/output binding', () => {
comp.childMessage = expectedMessage;
fixture.detectChanges();

fixture.whenStable().then(() => {
fixture.detectChanges();
const childComponents = de.queryAll(By.directive(TestChildComponent));
expect(childComponents.length).toBe(3);
childComponents.forEach((childComponent) => {
expect(childComponent.nativeElement.innerHTML).toContain(expectedMessage);
});
await fixture.whenStable();
fixture.detectChanges();

const childComponents = de.queryAll(By.directive(TestChildComponent));
expect(childComponents.length).toBe(3);
childComponents.forEach((childComponent) => {
expect(childComponent.nativeElement.innerHTML).toContain(expectedMessage);
});
})
);

it(
'should bind outputs to children',
waitForAsync(() => {
waitForAsync(async () => {
comp.rendering = ({
placeholders: {
children: [
Expand All @@ -460,14 +451,14 @@ describe('<sc-placeholder /> with input/output binding', () => {
} as unknown) as ComponentRendering;
comp.name = 'children';
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
const button = de.query(By.css('button'));
button.nativeElement.click();
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();

expect(de.nativeElement.innerHTML).toContain('dolor');
});
const button = de.query(By.css('button'));
button.nativeElement.click();
fixture.detectChanges();

expect(de.nativeElement.innerHTML).toContain('dolor');
})
);
});
Loading