Merge remote-tracking branch 'origin/v10/dev' into v10/dev

This commit is contained in:
Bjarke Berg
2023-09-12 09:43:52 +02:00
5 changed files with 179 additions and 78 deletions

View File

@@ -19,6 +19,9 @@ public class Issuu : EmbedProviderBase
public override Dictionary<string, string> RequestParams => new()
{
// ApiUrl/?iframe=true
{ "iframe", "true" },
// ApiUrl/?format=xml
{ "format", "xml" },
};

View File

@@ -55,11 +55,12 @@ public abstract class OEmbedProviderBase : IEmbedProvider
if (_httpClient == null)
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("Umbraco-CMS");
}
using (var request = new HttpRequestMessage(HttpMethod.Get, url))
{
HttpResponseMessage response = _httpClient.SendAsync(request).Result;
HttpResponseMessage response = _httpClient.SendAsync(request).GetAwaiter().GetResult();
return response.Content.ReadAsStringAsync().Result;
}
}

View File

@@ -37,6 +37,7 @@ public static class PublishedModelUtility
switch (itemType)
{
case PublishedItemType.Content:
case PublishedItemType.Element:
return publishedSnapshot.Content?.GetContentType(alias);
case PublishedItemType.Media:
return publishedSnapshot.Media?.GetContentType(alias);

View File

@@ -5,7 +5,7 @@
ng-repeat="subView in subViews track by subView.alias"
ng-class="'sub-view-' + subView.name"
val-sub-view="subView"
ng-if="subView.active"
ng-show="subView.active"
>
<div class="umb-editor-sub-view__content" ng-include="subView.view"></div>
</div>

View File

@@ -6,24 +6,26 @@ import {BlockListDataTypeBuilder} from "@umbraco/json-models-builders/dist/lib/b
test.describe('BlockListEditorContent', () => {
const documentName = 'DocumentTestName';
const blockListName = 'BlockListTest';
const elementName = 'TestElement';
const contentElementName = 'ContentElement';
const settingElementName = 'SettingsElement';
const documentAlias = AliasHelper.toAlias(documentName);
const blockListAlias = AliasHelper.toAlias(blockListName);
// Won't work if I use the to alias for the elementAlias
const elementAlias = 'testElement';
// Won't work if we use the to alias for the elementAliases
const contentElementAlias = 'contentElement';
const settingsElementAlias = 'settingsElement';
test.beforeEach(async ({page, umbracoApi, umbracoUi}, testInfo) => {
await umbracoApi.report.report(testInfo);
await umbracoApi.login();
await umbracoApi.documentTypes.ensureNameNotExists(documentName);
await umbracoApi.documentTypes.ensureNameNotExists(elementName);
await umbracoApi.documentTypes.ensureNameNotExists(contentElementName);
await umbracoApi.dataTypes.ensureNameNotExists(blockListName);
});
test.afterEach(async ({page, umbracoApi, umbracoUi}) => {
await umbracoApi.documentTypes.ensureNameNotExists(documentName);
await umbracoApi.documentTypes.ensureNameNotExists(elementName);
await umbracoApi.documentTypes.ensureNameNotExists(contentElementName);
await umbracoApi.dataTypes.ensureNameNotExists(blockListName);
});
@@ -31,23 +33,22 @@ test.describe('BlockListEditorContent', () => {
const dataTypeBlockList = new BlockListDataTypeBuilder()
.withName(blockListName)
.addBlock()
.withContentElementTypeKey(element['key'])
.withSettingsElementTypeKey(element['key'])
.withContentElementTypeKey(element['key'])
.withSettingsElementTypeKey(element['key'])
.done()
.build();
return await umbracoApi.dataTypes.save(dataTypeBlockList);
}
async function createDocumentWithOneBlockListEditor(umbracoApi, element, dataType){
async function createDocumentWithOneBlockListEditor(umbracoApi, element, dataType, elementName?, elementAlias?){
if(element == null) {
element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias);
}
if(dataType == null) {
dataType = await createDefaultBlockList(umbracoApi, blockListName, element);
}
const docType = new DocumentTypeBuilder()
.withName(documentName)
.withAlias(documentAlias)
@@ -61,16 +62,15 @@ test.describe('BlockListEditorContent', () => {
.done()
.build();
await umbracoApi.documentTypes.save(docType);
return element;
}
async function createContentWithOneBlockListEditor(umbracoApi, element) {
async function createContentWithOneBlockListEditor(umbracoApi, element, datatype?, elementName?, elementAlias?) {
if(element == null) {
element = await createDocumentWithOneBlockListEditor(umbracoApi, null, null);
element = await createDocumentWithOneBlockListEditor(umbracoApi, null, datatype, elementName, elementAlias);
}
const rootContentNode = new ContentBuilder()
.withContentTypeAlias(documentAlias)
.withAction(ConstantHelper.actions.save)
@@ -89,13 +89,35 @@ test.describe('BlockListEditorContent', () => {
.done()
.build();
await umbracoApi.content.save(rootContentNode);
return element;
}
async function createElementWithSlider(umbracoApi, name, alias, sliderId, sliderName?, sliderDefaultValue?) {
if (sliderId == null) {
const sliderData = await umbracoApi.dataTypes.createSliderWithDefaultValue(sliderName, sliderDefaultValue);
sliderId = sliderData.id;
}
const contentElement = new DocumentTypeBuilder()
.withName(name)
.withAlias(alias)
.AsElementType()
.addGroup()
.withName('Content')
.withAlias('content')
.addCustomProperty(sliderId)
.withLabel('Slider')
.withAlias('slider')
.done()
.done()
.build();
return await umbracoApi.documentTypes.save(contentElement);
}
test('can create content with a block list editor', async ({page, umbracoApi, umbracoUi}) => {
await createDocumentWithOneBlockListEditor(umbracoApi, null, null);
await createDocumentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias);
const rootContentNode = new ContentBuilder()
.withContentTypeAlias(documentAlias)
.withAction(ConstantHelper.actions.save)
@@ -113,7 +135,7 @@ test.describe('BlockListEditorContent', () => {
await umbracoUi.clickDataElementByElementName('tree-item-' + blockListName);
// Adds TestElement
await page.locator('[key="blockEditor_addThis"]', {hasText: elementName}).click();
await page.locator('[key="blockEditor_addThis"]', {hasText: contentElementName}).click();
await page.locator('[id="sub-view-0"]').locator('[id="title"]').fill('Testing...');
await page.locator('[label="Create"]').click();
@@ -121,17 +143,17 @@ test.describe('BlockListEditorContent', () => {
// Assert
await umbracoUi.isSuccessNotificationVisible();
// Checks if the content was created
await expect(page.locator('.umb-block-list__block--view')).toHaveCount(1);
await expect(page.locator('.umb-block-list__block--view').nth(0)).toHaveText(elementName);
await expect(page.locator('.umb-block-list__block--view')).toHaveText(contentElementName);
// Checks if the content contains the correct value
await page.locator('.umb-block-list__block--view').nth(0).click();
await page.locator('.umb-block-list__block--view', {hasText: contentElementName}).click();
await expect(page.locator('[id="sub-view-0"]').locator('[id="title"]')).toHaveValue('Testing...');
});
test('can update content with a block list editor', async ({page, umbracoApi, umbracoUi}) => {
await createContentWithOneBlockListEditor(umbracoApi, null);
await createContentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias);
await umbracoUi.goToSection(ConstantHelper.sections.content);
await umbracoUi.refreshContentTree();
@@ -154,7 +176,7 @@ test.describe('BlockListEditorContent', () => {
});
test('can delete a block list editor in content', async ({page, umbracoApi, umbracoUi}) => {
await createContentWithOneBlockListEditor(umbracoApi, null);
await createContentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias);
await umbracoUi.goToSection(ConstantHelper.sections.content);
await umbracoUi.refreshContentTree();
@@ -172,13 +194,13 @@ test.describe('BlockListEditorContent', () => {
// Assert
await umbracoUi.isSuccessNotificationVisible();
// Checks if the content is actually deleted
await expect(page.locator('[ui-sortable="vm.sortableOptions"]').nth(0)).not.toBeVisible();
});
test('can copy block list content and paste it', async ({page, umbracoApi, umbracoUi}) => {
await createContentWithOneBlockListEditor(umbracoApi, null);
await createContentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias);
await umbracoUi.goToSection(ConstantHelper.sections.content);
await umbracoUi.refreshContentTree();
@@ -194,7 +216,7 @@ test.describe('BlockListEditorContent', () => {
await expect(page.locator('.alert-success', {hasText: 'Copied to clipboard'})).toBeVisible();
// Pastes block list content
await page.locator('[title="Clipboard"]').click();
await page.locator('umb-block-card', {hasText: elementName}).click();
await page.locator('umb-block-card', {hasText: contentElementName}).click();
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish));
// Assert
@@ -204,9 +226,9 @@ test.describe('BlockListEditorContent', () => {
});
test('can copy block list content and paste it into another group with the same block list editor', async ({page, umbracoApi, umbracoUi}) => {
const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias);
const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias);
const dataType = await createDefaultBlockList(umbracoApi, blockListName, element);
const dataType = await createDefaultBlockList(umbracoApi, blockListName, contentElement);
const docType = new DocumentTypeBuilder()
.withName(documentName)
@@ -227,7 +249,7 @@ test.describe('BlockListEditorContent', () => {
.build();
await umbracoApi.documentTypes.save(docType);
await createContentWithOneBlockListEditor(umbracoApi, element);
await createContentWithOneBlockListEditor(umbracoApi, contentElement);
await umbracoUi.goToSection(ConstantHelper.sections.content);
await umbracoUi.refreshContentTree();
@@ -245,7 +267,7 @@ test.describe('BlockListEditorContent', () => {
await expect(page.locator('.alert-success', {hasText: 'Copied to clipboard'})).toBeVisible();
// Pastes into the second group
await page.locator('[title="Clipboard"]').nth(1).click();
await page.locator('umb-block-card', {hasText: elementName}).click();
await page.locator('umb-block-card', {hasText: contentElementName}).click();
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish));
await expect(page.locator('.alert-success', {hasText: 'Content Published'})).toBeVisible();
@@ -257,20 +279,20 @@ test.describe('BlockListEditorContent', () => {
});
test('can set a minimum of required blocks in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => {
const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias);
const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias);
const dataTypeBlockList = new BlockListDataTypeBuilder()
.withName(blockListName)
.withMin(2)
.addBlock()
.withContentElementTypeKey(element['key'])
.withContentElementTypeKey(contentElement['key'])
.done()
.build();
const dataType = await umbracoApi.dataTypes.save(dataTypeBlockList);
await createDocumentWithOneBlockListEditor(umbracoApi, element, dataType);
await createContentWithOneBlockListEditor(umbracoApi, element);
await createDocumentWithOneBlockListEditor(umbracoApi, contentElement, dataType);
await createContentWithOneBlockListEditor(umbracoApi, contentElement);
await umbracoUi.goToSection(ConstantHelper.sections.content);
await umbracoUi.refreshContentTree();
@@ -294,18 +316,18 @@ test.describe('BlockListEditorContent', () => {
});
test('can set a maximum of required blocks in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => {
const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias);
const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias);
const dataTypeBlockList = new BlockListDataTypeBuilder()
.withName(blockListName)
.withMax(2)
.addBlock()
.withContentElementTypeKey(element['key'])
.withContentElementTypeKey(contentElement['key'])
.done()
.build();
const dataType = await umbracoApi.dataTypes.save(dataTypeBlockList);
await createDocumentWithOneBlockListEditor(umbracoApi, element, dataType);
await createDocumentWithOneBlockListEditor(umbracoApi, contentElement, dataType);
const rootContentNode = new ContentBuilder()
.withContentTypeAlias(documentAlias)
@@ -317,16 +339,16 @@ test.describe('BlockListEditorContent', () => {
.withAlias(blockListAlias)
.addBlockListValue()
.addBlockListEntry()
.withContentTypeKey(element['key'])
.appendContentProperties(element.groups[0].properties[0].alias, "aliasTest")
.withContentTypeKey(contentElement['key'])
.appendContentProperties(contentElement.groups[0].properties[0].alias, "aliasTest")
.done()
.addBlockListEntry()
.withContentTypeKey(element['key'])
.appendContentProperties(element.groups[0].properties[0].alias, "aliasTests")
.withContentTypeKey(contentElement['key'])
.appendContentProperties(contentElement.groups[0].properties[0].alias, "aliasTests")
.done()
.addBlockListEntry()
.withContentTypeKey(element['key'])
.appendContentProperties(element.groups[0].properties[0].alias, "aliasTester")
.withContentTypeKey(contentElement['key'])
.appendContentProperties(contentElement.groups[0].properties[0].alias, "aliasTester")
.done()
.done()
.done()
@@ -357,20 +379,20 @@ test.describe('BlockListEditorContent', () => {
});
test('can use inline editing mode in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => {
const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias);
const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias);
const dataTypeBlockList = new BlockListDataTypeBuilder()
.withName(blockListName)
.withUseInlineEditingAsDefault(true)
.addBlock()
.withContentElementTypeKey(element['key'])
.withContentElementTypeKey(contentElement['key'])
.done()
.build();
const dataType = await umbracoApi.dataTypes.save(dataTypeBlockList);
await createDocumentWithOneBlockListEditor(umbracoApi, element, dataType);
await createContentWithOneBlockListEditor(umbracoApi, element);
await createDocumentWithOneBlockListEditor(umbracoApi, contentElement, dataType);
await createContentWithOneBlockListEditor(umbracoApi, contentElement);
await umbracoUi.goToSection(ConstantHelper.sections.content);
await umbracoUi.refreshContentTree();
@@ -387,11 +409,11 @@ test.describe('BlockListEditorContent', () => {
test('can see rendered content with a block list editor', async ({page, umbracoApi, umbracoUi}) => {
await umbracoApi.templates.ensureNameNotExists(documentName);
await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',elementAlias + '.cshtml');
await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',contentElementAlias + '.cshtml');
const element = new DocumentTypeBuilder()
.withName(elementName)
.withAlias(elementAlias)
const contentElement = new DocumentTypeBuilder()
.withName(contentElementName)
.withAlias(contentElementAlias)
.AsElementType()
.addGroup()
.withName("TestString")
@@ -406,9 +428,9 @@ test.describe('BlockListEditorContent', () => {
.done()
.done()
.build();
await umbracoApi.documentTypes.save(element);
await umbracoApi.documentTypes.save(contentElement);
const dataType = await createDefaultBlockList(umbracoApi, blockListName, element);
const dataType = await createDefaultBlockList(umbracoApi, blockListName, contentElement);
const docType = new DocumentTypeBuilder()
.withName(documentName)
@@ -418,7 +440,7 @@ test.describe('BlockListEditorContent', () => {
.addGroup()
.withName('BlockListGroup')
.addCustomProperty(dataType['id'])
.withAlias(elementAlias)
.withAlias(contentElementAlias)
.done()
.done()
.build();
@@ -431,15 +453,15 @@ test.describe('BlockListEditorContent', () => {
'\n Layout = null;' +
'\n}' +
'\n' +
'@Html.GetBlockListHtml(Model.' + elementName + ')');
'@Html.GetBlockListHtml(Model.' + contentElementName + ')');
const partialView = new PartialViewBuilder()
.withName(elementAlias)
.withName(contentElementAlias)
.withContent("@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockListItem>;\n" +
"@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;\n" +
"@{\n" +
"var content = (ContentModels." + elementName + ")Model.Content;\n" +
"var settings = (ContentModels." + elementName + ")Model.Settings;\n" +
"var content = (ContentModels." + contentElementName + ")Model.Content;\n" +
"var settings = (ContentModels." + contentElementName + ")Model.Settings;\n" +
"}\n" +
"\n" +
"<h1>@content.Title</h1>" +
@@ -459,15 +481,15 @@ test.describe('BlockListEditorContent', () => {
.withSave(true)
.withPublish(true)
.addProperty()
.withAlias(elementAlias)
.withAlias(contentElementAlias)
.addBlockListValue()
.addBlockListEntry()
.withContentTypeKey(element['key'])
.appendContentProperties(element.groups[0].properties[0].alias, "ContentTest")
.appendContentProperties(element.groups[0].properties[1].alias, "RTEContent")
.withSettingsTypeKey(element['key'])
.appendSettingsProperties(element.groups[0].properties[0].alias, "SettingTest")
.appendSettingsProperties(element.groups[0].properties[1].alias, "RTESetting")
.withContentTypeKey(contentElement['key'])
.appendContentProperties(contentElement.groups[0].properties[0].alias, "ContentTest")
.appendContentProperties(contentElement.groups[0].properties[1].alias, "RTEContent")
.withSettingsTypeKey(contentElement['key'])
.appendSettingsProperties(contentElement.groups[0].properties[0].alias, "SettingTest")
.appendSettingsProperties(contentElement.groups[0].properties[1].alias, "RTESetting")
.done()
.done()
.done()
@@ -479,9 +501,83 @@ test.describe('BlockListEditorContent', () => {
// Ensure that the view gets rendered correctly
const expected = `<divclass="umb-block-list"><h1>ContentTest</h1><p>RTEContent</p><h1>SettingTest</h1><p>RTESetting</p></div>`;
await expect(await umbracoApi.content.verifyRenderedContent('/', expected, true)).toBeTruthy();
// Clean
await umbracoApi.templates.ensureNameNotExists(documentName);
await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',elementAlias + '.cshtml');
await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',contentElementAlias + '.cshtml');
});
});
test('Checks if the settings content model contains a default value when created', async ({page, umbracoApi, umbracoUi}) => {
const contentSliderName = 'ContentSlider';
const contentSliderDefaultValue = 5;
const settingsSliderName = 'SettingsSlider';
const settingsSliderDefaultValue = 9;
await umbracoApi.documentTypes.ensureNameNotExists(settingElementName);
await umbracoApi.dataTypes.ensureNameNotExists(contentSliderName);
await umbracoApi.dataTypes.ensureNameNotExists(settingsSliderName);
const contentElement = await createElementWithSlider(umbracoApi, contentElementName, contentElementAlias, null, contentSliderName, contentSliderDefaultValue);
const settingsElement = await createElementWithSlider(umbracoApi, settingElementName, settingsElementAlias, null, settingsSliderName, settingsSliderDefaultValue);
const blockList = new BlockListDataTypeBuilder()
.withName(blockListName)
.addBlock()
.withContentElementTypeKey(contentElement['key'])
.withSettingsElementTypeKey(settingsElement['key'])
.done()
.build();
const blockListDataType = await umbracoApi.dataTypes.save(blockList);
const document = new DocumentTypeBuilder()
.withName(documentName)
.withAlias(documentAlias)
.withAllowAsRoot(true)
.addGroup()
.withName('Content')
.withAlias('content')
.addCustomProperty(blockListDataType['id'])
.withLabel('BlockListTest')
.withAlias('blockListTest')
.done()
.done()
.build();
await umbracoApi.documentTypes.save(document);
const content = new ContentBuilder()
.withContentTypeAlias(documentAlias)
.withAction(ConstantHelper.actions.publish)
.addVariant()
.withName(blockListName)
.withSave(true)
.withPublish(true)
.done()
.build();
const contentNode = await umbracoApi.content.save(content);
await umbracoUi.goToSection(ConstantHelper.sections.content);
await umbracoUi.refreshContentTree();
await umbracoUi.clickDataElementByElementName('tree-item-' + blockListName);
await page.locator('[key="blockEditor_addThis"]', {hasText: contentElementName}).click();
await page.locator('[label="Create"]').click();
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish));
// Assert
// Checks if the content contains the BlockListEditor block
await umbracoUi.clickDataElementByElementName("tree-root");
await umbracoUi.refreshContentTree();
await umbracoUi.clickDataElementByElementName('tree-item-' + blockListName);
await expect(page.locator('.umb-block-list__block--view')).toHaveCount(1);
// Checks if both the content and settings have been assigned their DefaultValues
const contentData = await umbracoApi.content.getContent(contentNode.id);
await expect(contentData.variants[0].tabs[0].properties[0].value.contentData[0].slider).toEqual(contentSliderDefaultValue.toString());
await expect(contentData.variants[0].tabs[0].properties[0].value.settingsData[0].slider).toEqual(settingsSliderDefaultValue.toString());
// Clean
await umbracoApi.documentTypes.ensureNameNotExists(settingElementName);
await umbracoApi.dataTypes.ensureNameNotExists(contentSliderName);
await umbracoApi.dataTypes.ensureNameNotExists(settingsSliderName);
});
});