Merge branch 'v15/dev' into v16/dev
This commit is contained in:
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -4,11 +4,11 @@ contact_links:
|
||||
url: https://github.com/umbraco/Umbraco-CMS/discussions/new?category=features-and-ideas
|
||||
about: Start a new discussion when you have ideas or feature requests, eventually discussions can turn into plans
|
||||
- name: ⁉️ Support Question
|
||||
url: https://our.umbraco.com
|
||||
url: https://forum.umbraco.com
|
||||
about: This issue tracker is NOT meant for support questions. If you have a question, please join us on the forum.
|
||||
- name: 📖 Documentation Issue
|
||||
url: https://github.com/umbraco/UmbracoDocs/issues
|
||||
about: Documentation issues should be reported on the Umbraco documentation repository.
|
||||
- name: 🔐 Security Issue
|
||||
url: https://umbraco.com/about-us/trust-center/security-and-umbraco/how-to-report-a-vulnerability-in-umbraco/
|
||||
url: https://umbraco.com/trust-center/security-and-umbraco/how-to-report-a-vulnerability-in-umbraco/
|
||||
about: Discovered a Security Issue in Umbraco?
|
||||
|
||||
2
.github/README.md
vendored
2
.github/README.md
vendored
@@ -4,8 +4,8 @@
|
||||
[](https://www.nuget.org/packages/Umbraco.Cms)
|
||||
[](https://umbraco.visualstudio.com/Umbraco%20Cms/_build?definitionId=301)
|
||||
[](CONTRIBUTING.md)
|
||||
[](https://forum.umbraco.com)
|
||||
[](https://discord.gg/umbraco)
|
||||
[](https://discord-chats.umbraco.com)
|
||||

|
||||
|
||||
|
||||
|
||||
@@ -26,23 +26,36 @@
|
||||
<ProjectReference Include="..\Umbraco.Web.Website\Umbraco.Web.Website.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Restore and build backoffice project -->
|
||||
<!-- General ignored files -->
|
||||
<ItemGroup>
|
||||
<Content Remove="wwwroot\umbraco\assets\README.md" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<!-- BEGIN: Restore and build backoffice project -->
|
||||
<PropertyGroup>
|
||||
<BackofficeProjectDirectory Condition="'$(BackofficeProjectDirectory)' == ''">..\Umbraco.Web.UI.Client\</BackofficeProjectDirectory>
|
||||
<BackofficeAssetsPath>wwwroot\umbraco\backoffice</BackofficeAssetsPath>
|
||||
<BackofficeAssetsPath>$(ProjectDir)wwwroot\umbraco\backoffice</BackofficeAssetsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<BackofficeAssetsInputs Include="$(BackofficeProjectDirectory)package.json;$(BackofficeProjectDirectory)package-lock.json;$(BackofficeProjectDirectory)src\**" Exclude="$(DefaultItemExcludes)" />
|
||||
<Content Remove="$(BackofficeAssetsPath)\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="RestoreBackoffice" Inputs="$(BackofficeProjectDirectory)package-lock.json" Outputs="$(BackofficeProjectDirectory)node_modules\.package-lock.json">
|
||||
<Message Importance="high" Text="Restoring Backoffice NPM packages..." />
|
||||
<Exec Command="npm ci --no-fund --no-audit --prefer-offline" WorkingDirectory="$(BackofficeProjectDirectory)" />
|
||||
<Target Name="BuildStaticAssetsPreconditions" BeforeTargets="AssignTargetPaths">
|
||||
<Message Text="Skip BuildBackoffice target because UmbracoBuild is '$(UmbracoBuild)' (this is not Visual Studio)" Importance="high" Condition="'$(UmbracoBuild)' != ''" />
|
||||
<Message Text="Skip BuildBackoffice target because '$(BackofficeAssetsPath)' already exists" Importance="high" Condition="Exists('$(BackofficeAssetsPath)')" />
|
||||
<Message Text="Call BuildBackoffice target because UmbracoBuild is empty (this is Visual Studio) and '$(BackofficeAssetsPath)' doesn't exist" Importance="high" Condition="'$(UmbracoBuild)' == '' and !Exists('$(BackofficeAssetsPath)')" />
|
||||
<CallTarget Targets="BuildBackoffice" Condition="'$(UmbracoBuild)' == '' and !Exists('$(BackofficeAssetsPath)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildBackoffice" DependsOnTargets="RestoreBackoffice" BeforeTargets="AssignTargetPaths" Inputs="@(BackofficeAssetsInputs)" Outputs="$(IntermediateOutputPath)backoffice.complete.txt">
|
||||
<Target Name="RestoreBackoffice" Inputs="$(BackofficeProjectDirectory)package-lock.json" Outputs="$(BackofficeProjectDirectory)node_modules\.package-lock.json">
|
||||
<Message Importance="high" Text="Restoring Backoffice NPM packages..." />
|
||||
<Exec Command="npm i --no-fund --no-audit" WorkingDirectory="$(BackofficeProjectDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildBackoffice" DependsOnTargets="RestoreBackoffice">
|
||||
<Message Importance="high" Text="Executing Backoffice NPM build script..." />
|
||||
<Exec Command="npm run build:for:cms" WorkingDirectory="$(BackofficeProjectDirectory)" />
|
||||
<ItemGroup>
|
||||
@@ -61,27 +74,46 @@
|
||||
</DefineStaticWebAssets>
|
||||
</Target>
|
||||
|
||||
<!-- Restore and build login project -->
|
||||
<Target Name="CleanStaticAssetsPreconditions" AfterTargets="Clean" Condition="'$(UmbracoBuild)' == ''">
|
||||
<Message Text="Skip CleanBackoffice target because '$(BackofficeAssetsPath)' doesn't exist" Importance="high" Condition="!Exists('$(BackofficeAssetsPath)')" />
|
||||
<Message Text="Skip CleanBackoffice target because preserve.backoffice marker file exists" Importance="high" Condition="Exists('$(BackofficeAssetsPath)') and Exists('$(SolutionDir)preserve.backoffice')" />
|
||||
<Message Text="Call CleanBackoffice target because '$(BackofficeAssetsPath)' exists and preserve.backoffice marker file doesn't exist" Importance="high" Condition="Exists('$(BackofficeAssetsPath)') and !Exists('$(SolutionDir)preserve.backoffice')" />
|
||||
<CallTarget Targets="CleanBackoffice" Condition="Exists('$(BackofficeAssetsPath)') and !Exists('$(SolutionDir)preserve.backoffice')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CleanBackoffice">
|
||||
<ItemGroup>
|
||||
<BackofficeDirectories Include="$(BackofficeAssetsPath)" />
|
||||
</ItemGroup>
|
||||
<RemoveDir Directories="@(BackofficeDirectories)" />
|
||||
</Target>
|
||||
<!-- END: Restore and build backoffice project -->
|
||||
|
||||
|
||||
|
||||
<!-- BEGIN: Restore and build login project -->
|
||||
<PropertyGroup>
|
||||
<LoginProjectDirectory Condition="'$(LoginProjectDirectory)' == ''">..\Umbraco.Web.UI.Login\</LoginProjectDirectory>
|
||||
<LoginAssetsPath>wwwroot\umbraco\login</LoginAssetsPath>
|
||||
<LoginAssetsPath>$(ProjectDir)wwwroot\umbraco\login</LoginAssetsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<LoginAssetsInputs Include="$(LoginProjectDirectory)**" Exclude="$(DefaultItemExcludes)" />
|
||||
<Content Remove="$(LoginAssetsPath)\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="wwwroot\umbraco\assets\README.md" />
|
||||
</ItemGroup>
|
||||
<Target Name="BuildLoginStaticAssetsPreconditions" BeforeTargets="AssignTargetPaths">
|
||||
<Message Text="Skip BuildLogin target because UmbracoBuild is '$(UmbracoBuild)' (this is not Visual Studio)" Importance="high" Condition="'$(UmbracoBuild)' != ''" />
|
||||
<Message Text="Skip BuildLogin target because '$(LoginAssetsPath)' already exists" Importance="high" Condition="Exists('$(LoginAssetsPath)')" />
|
||||
<Message Text="Call BuildLogin target because UmbracoBuild is empty (this is Visual Studio) and '$(LoginAssetsPath)' doesn't exist" Importance="high" Condition="'$(UmbracoBuild)' == '' and !Exists('$(LoginAssetsPath)')" />
|
||||
<CallTarget Targets="BuildLogin" Condition="'$(UmbracoBuild)' == '' and !Exists('$(LoginAssetsPath)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RestoreLogin" Inputs="$(LoginProjectDirectory)package-lock.json" Outputs="$(LoginProjectDirectory)node_modules/.package-lock.json">
|
||||
<Message Importance="high" Text="Restoring Login NPM packages..." />
|
||||
<Exec Command="npm ci --no-fund --no-audit --prefer-offline" WorkingDirectory="$(LoginProjectDirectory)" />
|
||||
<Exec Command="npm i --no-fund --no-audit" WorkingDirectory="$(LoginProjectDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildLogin" DependsOnTargets="RestoreLogin" BeforeTargets="AssignTargetPaths" Inputs="@(LoginAssetsInputs)" Outputs="$(IntermediateOutputPath)login.complete.txt">
|
||||
<Target Name="BuildLogin" DependsOnTargets="RestoreLogin">
|
||||
<Message Importance="high" Text="Executing Login NPM build script..." />
|
||||
<Exec Command="npm run build" WorkingDirectory="$(LoginProjectDirectory)" />
|
||||
<ItemGroup>
|
||||
@@ -99,4 +131,19 @@
|
||||
<Output TaskParameter="Assets" ItemName="StaticWebAsset" />
|
||||
</DefineStaticWebAssets>
|
||||
</Target>
|
||||
|
||||
<Target Name="CleanLoginStaticAssetsPreconditions" AfterTargets="Clean" Condition="'$(UmbracoBuild)' == ''">
|
||||
<Message Text="Skip CleanLogin target because '$(LoginAssetsPath)' doesn't exist" Importance="high" Condition="!Exists('$(LoginAssetsPath)')" />
|
||||
<Message Text="Skip CleanLogin target because preserve.login marker file exists" Importance="high" Condition="Exists('$(LoginAssetsPath)') and Exists('$(SolutionDir)preserve.login')" />
|
||||
<Message Text="Call CleanLogin target because '$(LoginAssetsPath)' exists and preserve.login marker file doesn't exist" Importance="high" Condition="Exists('$(LoginAssetsPath)') and !Exists('$(SolutionDir)preserve.login')" />
|
||||
<CallTarget Targets="CleanLogin" Condition="Exists('$(LoginAssetsPath)') and !Exists('$(SolutionDir)preserve.login')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CleanLogin">
|
||||
<ItemGroup>
|
||||
<LoginDirectories Include="$(LoginAssetsPath)" />
|
||||
</ItemGroup>
|
||||
<RemoveDir Directories="@(LoginDirectories)" />
|
||||
</Target>
|
||||
<!-- END: Restore and build login project -->
|
||||
</Project>
|
||||
|
||||
@@ -1,27 +1,40 @@
|
||||
import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers';
|
||||
import {expect} from "@playwright/test";
|
||||
import {
|
||||
ConstantHelper,
|
||||
NotificationConstantHelper,
|
||||
test,
|
||||
} from "@umbraco/playwright-testhelpers";
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
const contentName = 'TestContent';
|
||||
const documentTypeName = 'TestDocumentTypeForContent';
|
||||
const customDataTypeName = 'Test RTE Tiptap';
|
||||
const contentName = "TestContent";
|
||||
const documentTypeName = "TestDocumentTypeForContent";
|
||||
const customDataTypeName = "Test RTE Tiptap";
|
||||
let customDataTypeId = null;
|
||||
|
||||
test.beforeEach(async ({umbracoApi}) => {
|
||||
customDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customDataTypeName);
|
||||
test.beforeEach(async ({ umbracoApi }) => {
|
||||
customDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(
|
||||
customDataTypeName
|
||||
);
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentTypeName);
|
||||
await umbracoApi.document.ensureNameNotExists(contentName);
|
||||
});
|
||||
|
||||
test.afterEach(async ({umbracoApi}) => {
|
||||
test.afterEach(async ({ umbracoApi }) => {
|
||||
await umbracoApi.document.ensureNameNotExists(contentName);
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentTypeName);
|
||||
await umbracoApi.dataType.ensureNameNotExists(customDataTypeName);
|
||||
});
|
||||
|
||||
test('can create content with empty RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
test("can create content with empty RTE Tiptap property editor", async ({
|
||||
umbracoApi,
|
||||
umbracoUi,
|
||||
}) => {
|
||||
// Arrange
|
||||
const expectedState = 'Draft';
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
const expectedState = "Draft";
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(
|
||||
documentTypeName,
|
||||
customDataTypeName,
|
||||
customDataTypeId
|
||||
);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
@@ -41,11 +54,18 @@ test('can create content with empty RTE Tiptap property editor', async ({umbraco
|
||||
expect(contentData.values).toEqual([]);
|
||||
});
|
||||
|
||||
test('can create content with non-empty RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
test("can create content with non-empty RTE Tiptap property editor", async ({
|
||||
umbracoApi,
|
||||
umbracoUi,
|
||||
}) => {
|
||||
// Arrange
|
||||
const expectedState = 'Draft';
|
||||
const inputText = 'Test Tiptap here';
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
const expectedState = "Draft";
|
||||
const inputText = "Test Tiptap here";
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(
|
||||
documentTypeName,
|
||||
customDataTypeName,
|
||||
customDataTypeId
|
||||
);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
@@ -63,14 +83,24 @@ test('can create content with non-empty RTE Tiptap property editor', async ({umb
|
||||
expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy();
|
||||
const contentData = await umbracoApi.document.getByName(contentName);
|
||||
expect(contentData.variants[0].state).toBe(expectedState);
|
||||
expect(contentData.values[0].value.markup).toEqual('<p>' + inputText + '</p>');
|
||||
expect(contentData.values[0].value.markup).toEqual(
|
||||
"<p>" + inputText + "</p>"
|
||||
);
|
||||
});
|
||||
|
||||
test('can publish content with RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
test("can publish content with RTE Tiptap property editor", async ({
|
||||
umbracoApi,
|
||||
umbracoUi,
|
||||
}) => {
|
||||
// Arrange
|
||||
const expectedState = 'Published';
|
||||
const inputText = 'Test Tiptap here';
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
const expectedState = "Published";
|
||||
const inputText = "Test Tiptap here";
|
||||
const documentTypeId =
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(
|
||||
documentTypeName,
|
||||
customDataTypeName,
|
||||
customDataTypeId
|
||||
);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
@@ -86,46 +116,67 @@ test('can publish content with RTE Tiptap property editor', async ({umbracoApi,
|
||||
expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy();
|
||||
const contentData = await umbracoApi.document.getByName(contentName);
|
||||
expect(contentData.variants[0].state).toBe(expectedState);
|
||||
expect(contentData.values[0].value.markup).toEqual('<p>' + inputText + '</p>');
|
||||
expect(contentData.values[0].value.markup).toEqual(
|
||||
"<p>" + inputText + "</p>"
|
||||
);
|
||||
});
|
||||
|
||||
test.fixme('can add a media in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
test.fixme(
|
||||
"can add a media in RTE Tiptap property editor",
|
||||
async ({ umbracoApi, umbracoUi }) => {
|
||||
// Arrange
|
||||
const iconTitle = "Media Picker";
|
||||
const imageName = "Test Image For Content";
|
||||
await umbracoApi.media.ensureNameNotExists(imageName);
|
||||
await umbracoApi.media.createDefaultMediaWithImage(imageName);
|
||||
const documentTypeId =
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(
|
||||
documentTypeName,
|
||||
customDataTypeName,
|
||||
customDataTypeId
|
||||
);
|
||||
await umbracoApi.document.createDefaultDocument(
|
||||
contentName,
|
||||
documentTypeId
|
||||
);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
// fix this
|
||||
await umbracoUi.content.selectMediaWithName(imageName);
|
||||
await umbracoUi.content.clickChooseModalButton();
|
||||
await umbracoUi.content.clickMediaCaptionAltTextModalSubmitButton();
|
||||
await umbracoUi.content.clickSaveButton();
|
||||
|
||||
// Assert
|
||||
//await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.saved);
|
||||
await umbracoUi.content.isErrorNotificationVisible(false);
|
||||
expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy();
|
||||
const contentData = await umbracoApi.document.getByName(contentName);
|
||||
expect(contentData.values[0].value.markup).toContain("<img");
|
||||
expect(contentData.values[0].value.markup).toContain(imageName);
|
||||
|
||||
// Clean
|
||||
await umbracoApi.media.ensureNameNotExists(imageName);
|
||||
}
|
||||
);
|
||||
|
||||
test("can add a video in RTE Tiptap property editor", async ({
|
||||
umbracoApi,
|
||||
umbracoUi,
|
||||
}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Media Picker';
|
||||
const imageName = 'Test Image For Content';
|
||||
await umbracoApi.media.ensureNameNotExists(imageName);
|
||||
await umbracoApi.media.createDefaultMediaWithImage(imageName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
// fix this
|
||||
await umbracoUi.content.selectMediaWithName(imageName);
|
||||
await umbracoUi.content.clickChooseModalButton();
|
||||
await umbracoUi.content.clickMediaCaptionAltTextModalSubmitButton();
|
||||
await umbracoUi.content.clickSaveButton();
|
||||
|
||||
// Assert
|
||||
//await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.saved);
|
||||
await umbracoUi.content.isErrorNotificationVisible(false);
|
||||
expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy();
|
||||
const contentData = await umbracoApi.document.getByName(contentName);
|
||||
expect(contentData.values[0].value.markup).toContain('<img');
|
||||
expect(contentData.values[0].value.markup).toContain(imageName);
|
||||
|
||||
// Clean
|
||||
await umbracoApi.media.ensureNameNotExists(imageName);
|
||||
});
|
||||
|
||||
test('can add a video in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Embed';
|
||||
const videoURL = 'https://www.youtube.com/watch?v=Yu29dE-0OoI';
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
const iconTitle = "Embed";
|
||||
const videoURL = "https://www.youtube.com/watch?v=Yu29dE-0OoI";
|
||||
const documentTypeId =
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(
|
||||
documentTypeName,
|
||||
customDataTypeName,
|
||||
customDataTypeId
|
||||
);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
@@ -144,14 +195,22 @@ test('can add a video in RTE Tiptap property editor', async ({umbracoApi, umbrac
|
||||
await umbracoUi.content.isErrorNotificationVisible(false);
|
||||
expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy();
|
||||
const contentData = await umbracoApi.document.getByName(contentName);
|
||||
expect(contentData.values[0].value.markup).toContain('data-embed-url');
|
||||
expect(contentData.values[0].value.markup).toContain("data-embed-url");
|
||||
expect(contentData.values[0].value.markup).toContain(videoURL);
|
||||
});
|
||||
|
||||
test('cannot submit an empty link in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
test("cannot submit an empty link in RTE Tiptap property editor", async ({
|
||||
umbracoApi,
|
||||
umbracoUi,
|
||||
}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Link';
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
const iconTitle = "Link";
|
||||
const documentTypeId =
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(
|
||||
documentTypeName,
|
||||
customDataTypeName,
|
||||
customDataTypeId
|
||||
);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
@@ -160,21 +219,31 @@ test('cannot submit an empty link in RTE Tiptap property editor', async ({umbrac
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
await umbracoUi.content.clickManualLinkButton();
|
||||
await umbracoUi.content.enterLink('');
|
||||
await umbracoUi.content.enterAnchorOrQuerystring('');
|
||||
await umbracoUi.content.enterLinkTitle('');
|
||||
await umbracoUi.content.enterLink("");
|
||||
await umbracoUi.content.enterAnchorOrQuerystring("");
|
||||
await umbracoUi.content.enterLinkTitle("");
|
||||
await umbracoUi.content.clickAddButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.content.isTextWithMessageVisible(ConstantHelper.validationMessages.emptyLinkPicker);
|
||||
await umbracoUi.content.isTextWithMessageVisible(
|
||||
ConstantHelper.validationMessages.emptyLinkPicker
|
||||
);
|
||||
});
|
||||
|
||||
// TODO: Remove skip when the front-end ready. Currently it still accept the empty link with an anchor or querystring
|
||||
// Issue link: https://github.com/umbraco/Umbraco-CMS/issues/17411
|
||||
test.skip('cannot submit an empty URL with an anchor or querystring in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
test.skip("cannot submit an empty URL with an anchor or querystring in RTE Tiptap property editor", async ({
|
||||
umbracoApi,
|
||||
umbracoUi,
|
||||
}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Link';
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
const iconTitle = "Link";
|
||||
const documentTypeId =
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(
|
||||
documentTypeName,
|
||||
customDataTypeName,
|
||||
customDataTypeId
|
||||
);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
@@ -183,26 +252,42 @@ test.skip('cannot submit an empty URL with an anchor or querystring in RTE Tipta
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
await umbracoUi.content.clickManualLinkButton();
|
||||
await umbracoUi.content.enterLink('');
|
||||
await umbracoUi.content.enterAnchorOrQuerystring('#value');
|
||||
await umbracoUi.content.enterLink("");
|
||||
await umbracoUi.content.enterAnchorOrQuerystring("#value");
|
||||
await umbracoUi.content.clickAddButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.content.isTextWithMessageVisible(ConstantHelper.validationMessages.emptyLinkPicker);
|
||||
await umbracoUi.content.isTextWithMessageVisible(
|
||||
ConstantHelper.validationMessages.emptyLinkPicker
|
||||
);
|
||||
});
|
||||
|
||||
// TODO: Remove skip when the front-end ready. Currently it is impossible to link to unpublished document
|
||||
// Issue link: https://github.com/umbraco/Umbraco-CMS/issues/17974
|
||||
test.skip('can insert a link to an unpublished document in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
test.skip("can insert a link to an unpublished document in RTE Tiptap property editor", async ({
|
||||
umbracoApi,
|
||||
umbracoUi,
|
||||
}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Link';
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
const iconTitle = "Link";
|
||||
const documentTypeId =
|
||||
await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(
|
||||
documentTypeName,
|
||||
customDataTypeName,
|
||||
customDataTypeId
|
||||
);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
// Create a document to link
|
||||
const documentTypeForLinkedDocumentName = 'TestDocumentType';
|
||||
const documentTypeForLinkedDocumentId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeForLinkedDocumentName);
|
||||
const linkedDocumentName = 'LinkedDocument';
|
||||
await umbracoApi.document.createDefaultDocument(linkedDocumentName, documentTypeForLinkedDocumentId);
|
||||
const documentTypeForLinkedDocumentName = "TestDocumentType";
|
||||
const documentTypeForLinkedDocumentId =
|
||||
await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(
|
||||
documentTypeForLinkedDocumentName
|
||||
);
|
||||
const linkedDocumentName = "LinkedDocument";
|
||||
await umbracoApi.document.createDefaultDocument(
|
||||
linkedDocumentName,
|
||||
documentTypeForLinkedDocumentId
|
||||
);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
@@ -211,7 +296,7 @@ test.skip('can insert a link to an unpublished document in RTE Tiptap property e
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
await umbracoUi.content.clickDocumentLinkButton();
|
||||
await umbracoUi.content.selectLinkByName(linkedDocumentName);
|
||||
await umbracoUi.content.clickButtonWithName('Choose');
|
||||
await umbracoUi.content.clickButtonWithName("Choose");
|
||||
await umbracoUi.content.clickAddButton();
|
||||
await umbracoUi.content.clickSaveButton();
|
||||
|
||||
@@ -220,6 +305,8 @@ test.skip('can insert a link to an unpublished document in RTE Tiptap property e
|
||||
await umbracoUi.content.isErrorNotificationVisible(false);
|
||||
|
||||
// Clean
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentTypeForLinkedDocumentName);
|
||||
await umbracoApi.documentType.ensureNameNotExists(
|
||||
documentTypeForLinkedDocumentName
|
||||
);
|
||||
await umbracoApi.document.ensureNameNotExists(linkedDocumentName);
|
||||
});
|
||||
@@ -0,0 +1,190 @@
|
||||
import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers';
|
||||
import {expect} from "@playwright/test";
|
||||
|
||||
const contentName = 'TestContent';
|
||||
const documentTypeName = 'TestDocumentTypeForContent';
|
||||
const customDataTypeName = 'Test RTE Tiptap';
|
||||
|
||||
test.beforeEach(async ({umbracoApi}) => {
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentTypeName);
|
||||
await umbracoApi.document.ensureNameNotExists(contentName);
|
||||
});
|
||||
|
||||
test.afterEach(async ({umbracoApi}) => {
|
||||
await umbracoApi.document.ensureNameNotExists(contentName);
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentTypeName);
|
||||
await umbracoApi.dataType.ensureNameNotExists(customDataTypeName);
|
||||
});
|
||||
|
||||
test('can add a media in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Media Picker';
|
||||
const imageName = 'Test Image For Content';
|
||||
await umbracoApi.media.ensureNameNotExists(imageName);
|
||||
await umbracoApi.media.createDefaultMediaWithImage(imageName);
|
||||
const customDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customDataTypeName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
await umbracoUi.content.selectMediaWithName(imageName);
|
||||
await umbracoUi.content.clickChooseModalButton();
|
||||
await umbracoUi.content.clickMediaCaptionAltTextModalSubmitButton();
|
||||
await umbracoUi.content.clickSaveAndPublishButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.saved);
|
||||
await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.published);
|
||||
expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy();
|
||||
const contentData = await umbracoApi.document.getByName(contentName);
|
||||
expect(contentData.values[0].value.markup).toContain('<img');
|
||||
expect(contentData.values[0].value.markup).toContain(imageName);
|
||||
|
||||
// Clean
|
||||
await umbracoApi.media.ensureNameNotExists(imageName);
|
||||
});
|
||||
|
||||
test('can embed a video into RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Embed';
|
||||
const videoURL = 'https://www.youtube.com/watch?v=Yu29dE-0OoI';
|
||||
const customDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customDataTypeName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
await umbracoUi.content.enterEmbeddedURL(videoURL);
|
||||
await umbracoUi.content.clickEmbeddedRetrieveButton();
|
||||
await umbracoUi.content.waitForEmbeddedPreviewVisible();
|
||||
await umbracoUi.content.clickEmbeddedMediaModalConfirmButton();
|
||||
await umbracoUi.content.clickSaveButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.saved);
|
||||
expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy();
|
||||
const contentData = await umbracoApi.document.getByName(contentName);
|
||||
expect(contentData.values[0].value.markup).toContain('data-embed-url');
|
||||
expect(contentData.values[0].value.markup).toContain(videoURL);
|
||||
});
|
||||
|
||||
test('cannot submit an empty link in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Link';
|
||||
const customDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customDataTypeName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
await umbracoUi.content.clickManualLinkButton();
|
||||
await umbracoUi.content.enterLink('');
|
||||
await umbracoUi.content.enterAnchorOrQuerystring('');
|
||||
await umbracoUi.content.enterLinkTitle('');
|
||||
await umbracoUi.content.clickAddButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.content.isTextWithMessageVisible(ConstantHelper.validationMessages.emptyLinkPicker);
|
||||
});
|
||||
|
||||
// TODO: Remove skip when the front-end ready. Currently it still accept the empty link with an anchor or querystring
|
||||
// Issue link: https://github.com/umbraco/Umbraco-CMS/issues/17411
|
||||
test.skip('cannot submit an empty URL with an anchor or querystring in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Link';
|
||||
const customDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customDataTypeName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
await umbracoUi.content.clickManualLinkButton();
|
||||
await umbracoUi.content.enterLink('');
|
||||
await umbracoUi.content.enterAnchorOrQuerystring('#value');
|
||||
await umbracoUi.content.clickAddButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.content.isTextWithMessageVisible(ConstantHelper.validationMessages.emptyLinkPicker);
|
||||
});
|
||||
|
||||
// TODO: Remove skip when the front-end ready. Currently it is impossible to link to unpublished document
|
||||
// Issue link: https://github.com/umbraco/Umbraco-CMS/issues/17974
|
||||
test.skip('can insert a link to an unpublished document in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const iconTitle = 'Link';
|
||||
const customDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customDataTypeName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
// Create a document to link
|
||||
const documentTypeForLinkedDocumentName = 'TestDocumentType';
|
||||
const documentTypeForLinkedDocumentId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeForLinkedDocumentName);
|
||||
const linkedDocumentName = 'LinkedDocument';
|
||||
await umbracoApi.document.createDefaultDocument(linkedDocumentName, documentTypeForLinkedDocumentId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle);
|
||||
await umbracoUi.content.clickDocumentLinkButton();
|
||||
await umbracoUi.content.selectLinkByName(linkedDocumentName);
|
||||
await umbracoUi.content.clickButtonWithName('Choose');
|
||||
await umbracoUi.content.clickAddButton();
|
||||
await umbracoUi.content.clickSaveButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.content.isSuccessNotificationVisible();
|
||||
|
||||
// Clean
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentTypeForLinkedDocumentName);
|
||||
await umbracoApi.document.ensureNameNotExists(linkedDocumentName);
|
||||
});
|
||||
|
||||
test('can view word count', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const inputText = 'Test Tiptap <b>here</b>!!!';
|
||||
const expectedWordCount = 3;
|
||||
const customDataTypeId = await umbracoApi.dataType.createTiptapDataTypeWithWordCountStatusbar(customDataTypeName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.enterRTETipTapEditor(inputText);
|
||||
|
||||
// Assert
|
||||
await umbracoUi.content.doesTiptapHaveWordCount(expectedWordCount);
|
||||
});
|
||||
|
||||
test('can view element path', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const inputText = 'This is Tiptap test';
|
||||
const expectedElementPath = 'p';
|
||||
const customDataTypeId = await umbracoApi.dataType.createTiptapDataTypeWithElementPathStatusbar(customDataTypeName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.enterRTETipTapEditor(inputText);
|
||||
|
||||
// Assert
|
||||
await umbracoUi.content.doesElementPathHaveText(expectedElementPath);
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
import {ConstantHelper, test} from '@umbraco/playwright-testhelpers';
|
||||
import {expect} from "@playwright/test";
|
||||
|
||||
let collectionId = '';
|
||||
const contentName = 'TestContent';
|
||||
const documentTypeName = 'TestDocumentTypeForContent';
|
||||
const childDocumentTypeName = 'TestChildDocumentType';
|
||||
const firstChildContentName = 'First Child Content';
|
||||
const secondChildContentName = 'Second Child Content';
|
||||
const collectionDataTypeName = 'List View - Content';
|
||||
const referenceHeadline = ConstantHelper.trashDeleteDialogMessage.bulkReferenceHeadline;
|
||||
const documentPickerName = ['TestPicker', 'DocumentTypeForPicker'];
|
||||
|
||||
test.beforeEach(async ({umbracoApi}) => {
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentTypeName);
|
||||
await umbracoApi.document.ensureNameNotExists(contentName);
|
||||
const collectionDataTypeData = await umbracoApi.dataType.getByName(collectionDataTypeName);
|
||||
collectionId = collectionDataTypeData.id;
|
||||
});
|
||||
|
||||
test.afterEach(async ({umbracoApi}) => {
|
||||
await umbracoApi.document.ensureNameNotExists(contentName);
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentTypeName);
|
||||
await umbracoApi.documentType.ensureNameNotExists(childDocumentTypeName);
|
||||
await umbracoApi.document.emptyRecycleBin();
|
||||
});
|
||||
|
||||
test('can bulk trash content nodes without a relation', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const childDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentType(childDocumentTypeName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNodeAndCollectionId(documentTypeName, childDocumentTypeId, collectionId);
|
||||
const contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoApi.document.createDefaultDocumentWithParent(firstChildContentName, childDocumentTypeId, contentId);
|
||||
await umbracoApi.document.createDefaultDocumentWithParent(secondChildContentName, childDocumentTypeId, contentId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.selectContentWithNameInListView(firstChildContentName);
|
||||
await umbracoUi.content.selectContentWithNameInListView(secondChildContentName);
|
||||
await umbracoUi.content.clickTrashSelectedListItems();
|
||||
// Verify the references list not displayed
|
||||
await umbracoUi.content.isReferenceHeadlineVisible(false);
|
||||
await umbracoUi.content.clickConfirmTrashButton();
|
||||
|
||||
// // Assert
|
||||
await umbracoUi.content.isSuccessNotificationVisible();
|
||||
expect(await umbracoApi.document.doesNameExist(firstChildContentName)).toBeFalsy();
|
||||
expect(await umbracoApi.document.doesNameExist(secondChildContentName)).toBeFalsy();
|
||||
await umbracoUi.content.isItemVisibleInRecycleBin(firstChildContentName);
|
||||
await umbracoUi.content.isItemVisibleInRecycleBin(secondChildContentName);
|
||||
expect(await umbracoApi.document.doesItemExistInRecycleBin(firstChildContentName)).toBeTruthy();
|
||||
expect(await umbracoApi.document.doesItemExistInRecycleBin(secondChildContentName)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('can bulk trash content nodes with a relation', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const childDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentType(childDocumentTypeName);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNodeAndCollectionId(documentTypeName, childDocumentTypeId, collectionId);
|
||||
const contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoApi.document.publish(contentId);
|
||||
const firstChildContentId = await umbracoApi.document.createDefaultDocumentWithParent(firstChildContentName, childDocumentTypeId, contentId);
|
||||
await umbracoApi.document.publish(firstChildContentId);
|
||||
await umbracoApi.document.createDefaultDocumentWithParent(secondChildContentName, childDocumentTypeId, contentId);
|
||||
// Create a document that has a document picker with firstChildContentName
|
||||
await umbracoApi.document.createDefaultDocumentWithOneDocumentLink(documentPickerName[0], firstChildContentName, firstChildContentId, documentPickerName[1]);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
|
||||
// Act
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
await umbracoUi.content.selectContentWithNameInListView(firstChildContentName);
|
||||
await umbracoUi.content.selectContentWithNameInListView(secondChildContentName);
|
||||
await umbracoUi.content.clickTrashSelectedListItems();
|
||||
// Verify the references list
|
||||
await umbracoUi.content.doesReferenceHeadlineHaveText(referenceHeadline);
|
||||
await umbracoUi.content.doesReferenceItemsHaveCount(1);
|
||||
await umbracoUi.content.isReferenceItemNameVisible(firstChildContentName);
|
||||
await umbracoUi.content.clickConfirmTrashButton();
|
||||
|
||||
// // Assert
|
||||
await umbracoUi.content.isSuccessNotificationVisible();
|
||||
expect(await umbracoApi.document.doesNameExist(firstChildContentName)).toBeFalsy();
|
||||
expect(await umbracoApi.document.doesNameExist(secondChildContentName)).toBeFalsy();
|
||||
await umbracoUi.content.isItemVisibleInRecycleBin(firstChildContentName);
|
||||
await umbracoUi.content.isItemVisibleInRecycleBin(secondChildContentName);
|
||||
expect(await umbracoApi.document.doesItemExistInRecycleBin(firstChildContentName)).toBeTruthy();
|
||||
expect(await umbracoApi.document.doesItemExistInRecycleBin(secondChildContentName)).toBeTruthy();
|
||||
|
||||
// Clean
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentPickerName[1]);
|
||||
});
|
||||
@@ -6,7 +6,7 @@ const contentName = 'TestContent';
|
||||
const documentTypeName = 'TestDocumentTypeForContent';
|
||||
const dataTypeName = 'Textstring';
|
||||
const contentText = 'This is test content text';
|
||||
const referenceHeadline = 'The following items depend on this';
|
||||
const referenceHeadline = ConstantHelper.trashDeleteDialogMessage.referenceHeadline;
|
||||
const documentPickerName = ['TestPicker', 'DocumentTypeForPicker'];
|
||||
|
||||
test.beforeEach(async ({umbracoApi}) => {
|
||||
@@ -61,8 +61,8 @@ test('tiptap is the default property editor in rich text editor', async ({umbrac
|
||||
await umbracoUi.dataType.goToDataType(dataTypeName);
|
||||
|
||||
// Assert
|
||||
//await umbracoUi.dataType.doesSettingHaveValue(ConstantHelper.tipTapSettings);
|
||||
//await umbracoUi.dataType.doesSettingItemsHaveCount(ConstantHelper.tipTapSettings);
|
||||
await umbracoUi.dataType.doesSettingHaveValue(ConstantHelper.tipTapSettings);
|
||||
await umbracoUi.dataType.doesSettingItemsHaveCount(ConstantHelper.tipTapSettings);
|
||||
await umbracoUi.dataType.doesPropertyEditorHaveName(tipTapPropertyEditorName);
|
||||
await umbracoUi.dataType.doesPropertyEditorHaveAlias(tipTapAlias);
|
||||
await umbracoUi.dataType.doesPropertyEditorHaveUiAlias(tipTapUiAlias);
|
||||
|
||||
@@ -127,6 +127,7 @@ test('can add an available block', async ({umbracoApi, umbracoUi}) => {
|
||||
await umbracoUi.dataType.goToDataType(tipTapName);
|
||||
|
||||
// Act
|
||||
await umbracoUi.dataType.isExtensionItemChecked('Block', false);
|
||||
await umbracoUi.dataType.addAvailableBlocks(elementTypeName);
|
||||
await umbracoUi.dataType.clickSaveButton();
|
||||
|
||||
@@ -134,6 +135,8 @@ test('can add an available block', async ({umbracoApi, umbracoUi}) => {
|
||||
//await umbracoUi.dataType.doesSuccessNotificationHaveText(NotificationConstantHelper.success.saved);
|
||||
await umbracoUi.dataType.isErrorNotificationVisible(false);
|
||||
expect(await umbracoApi.dataType.doesRTEContainBlocks(tipTapName, [elementTypeId])).toBeTruthy();
|
||||
// Verify that "Block" extension is enable
|
||||
await umbracoUi.dataType.isExtensionItemChecked('Block');
|
||||
|
||||
// Clean
|
||||
await umbracoApi.documentType.ensureNameNotExists(elementTypeName);
|
||||
@@ -238,3 +241,38 @@ test('can disable extensions item', async ({umbracoApi, umbracoUi}) => {
|
||||
expect(extensionsValue.value.length).toBe(extensionsCount - 1);
|
||||
expect(extensionsValue.value).not.toContain(extensionItemName);
|
||||
});
|
||||
|
||||
test('can add a statusbar', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const statusbarName = 'Word Count';
|
||||
const statusbarApiValue = 'Umb.Tiptap.Statusbar.WordCount';
|
||||
await umbracoApi.dataType.createDefaultTiptapDataType(tipTapName);
|
||||
await umbracoUi.dataType.goToDataType(tipTapName);
|
||||
|
||||
// Act
|
||||
await umbracoUi.dataType.clickStatusbarItemInToolboxWithName(statusbarName);
|
||||
await umbracoUi.dataType.clickSaveButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.dataType.doesSuccessNotificationHaveText(NotificationConstantHelper.success.saved);
|
||||
const tipTapData = await umbracoApi.dataType.getByName(tipTapName);
|
||||
const statusbarValue = tipTapData.values.find(value => value.alias === 'statusbar');
|
||||
expect(statusbarValue.value).toEqual([[statusbarApiValue]]);
|
||||
});
|
||||
|
||||
test('can remove a statusbar', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const statusbarName = 'Word Count';
|
||||
await umbracoApi.dataType.createTiptapDataTypeWithWordCountStatusbar(tipTapName);
|
||||
await umbracoUi.dataType.goToDataType(tipTapName);
|
||||
|
||||
// Act
|
||||
await umbracoUi.dataType.clickStatusbarItemWithName(statusbarName);
|
||||
await umbracoUi.dataType.clickSaveButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.dataType.doesSuccessNotificationHaveText(NotificationConstantHelper.success.saved);
|
||||
const tipTapData = await umbracoApi.dataType.getByName(tipTapName);
|
||||
const statusbarValue = tipTapData.values.find(value => value.alias === 'statusbar');
|
||||
expect(statusbarValue).toBeFalsy();
|
||||
});
|
||||
@@ -178,6 +178,8 @@ test('can trash a media item', async ({umbracoApi, umbracoUi}) => {
|
||||
// Act
|
||||
await umbracoUi.media.clickActionsMenuForName(mediaFileName);
|
||||
await umbracoUi.media.clickTrashButton();
|
||||
// Verify the references list not displayed
|
||||
await umbracoUi.content.isReferenceHeadlineVisible(false);
|
||||
await umbracoUi.media.clickConfirmTrashButton();
|
||||
|
||||
// Assert
|
||||
@@ -250,3 +252,79 @@ test('can empty the recycle bin', async ({umbracoApi, umbracoUi}) => {
|
||||
expect(await umbracoApi.media.doesNameExist(mediaFileName)).toBeFalsy();
|
||||
expect(await umbracoApi.media.doesMediaItemExistInRecycleBin(mediaFileName)).toBeFalsy();
|
||||
});
|
||||
|
||||
test('can trash a media node with a relation', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const documentPickerName = ['TestPicker', 'DocumentTypeForPicker'];
|
||||
await umbracoApi.media.emptyRecycleBin();
|
||||
await umbracoApi.media.createDefaultMediaFile(mediaFileName);
|
||||
await umbracoApi.media.doesNameExist(mediaFileName);
|
||||
// Create a document that have media picker is firstMediaFileName
|
||||
await umbracoApi.document.createDefaultDocumentWithOneMediaLink(documentPickerName[0], mediaFileName, documentPickerName[1]);
|
||||
await umbracoUi.media.goToSection(ConstantHelper.sections.media);
|
||||
|
||||
// Act
|
||||
await umbracoUi.media.clickActionsMenuForName(mediaFileName);
|
||||
await umbracoUi.media.clickTrashButton();
|
||||
// Verify the references list
|
||||
await umbracoUi.media.doesReferenceHeadlineHaveText(ConstantHelper.trashDeleteDialogMessage.referenceHeadline);
|
||||
await umbracoUi.media.doesReferenceItemsHaveCount(1);
|
||||
await umbracoUi.media.isReferenceItemNameVisible(documentPickerName[0]);
|
||||
await umbracoUi.media.clickConfirmTrashButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.media.doesSuccessNotificationHaveText(NotificationConstantHelper.success.movedToRecycleBin);
|
||||
await umbracoUi.media.isItemVisibleInRecycleBin(mediaFileName);
|
||||
expect(await umbracoApi.media.doesNameExist(mediaFileName)).toBeFalsy();
|
||||
expect(await umbracoApi.media.doesMediaItemExistInRecycleBin(mediaFileName)).toBeTruthy();
|
||||
|
||||
// Clean
|
||||
await umbracoApi.media.emptyRecycleBin();
|
||||
await umbracoApi.document.ensureNameNotExists(documentPickerName[0]);
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentPickerName[1]);
|
||||
});
|
||||
|
||||
test('can bulk trash media nodes with a relation', async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const firstMediaFileName = 'FirstMediaFile';
|
||||
const secondMediaFileName = 'SecondMediaFile';
|
||||
const documentPickerName1 = ['TestPicker1', 'DocumentTypeForPicker1'];
|
||||
const documentPickerName2 = ['TestPicker2', 'DocumentTypeForPicker2'];
|
||||
await umbracoApi.media.emptyRecycleBin();
|
||||
await umbracoApi.media.createDefaultMediaFile(firstMediaFileName);
|
||||
await umbracoApi.media.createDefaultMediaFile(secondMediaFileName);
|
||||
// Create a document that has a media picker with firstMediaFileName
|
||||
await umbracoApi.document.createDefaultDocumentWithOneMediaLink(documentPickerName1[0], firstMediaFileName, documentPickerName1[1]);
|
||||
// Create a document that has a media picker with secondMediaFileName
|
||||
await umbracoApi.document.createDefaultDocumentWithOneMediaLink(documentPickerName2[0], secondMediaFileName, documentPickerName2[1]);
|
||||
|
||||
// Act
|
||||
await umbracoUi.media.goToSection(ConstantHelper.sections.media);
|
||||
await umbracoUi.media.selectMediaWithName(firstMediaFileName);
|
||||
await umbracoUi.media.selectMediaWithName(secondMediaFileName);
|
||||
await umbracoUi.media.clickBulkTrashButton();
|
||||
// Verify the references list
|
||||
await umbracoUi.media.doesReferenceHeadlineHaveText(ConstantHelper.trashDeleteDialogMessage.bulkReferenceHeadline);
|
||||
await umbracoUi.media.doesReferenceItemsHaveCount(2);
|
||||
await umbracoUi.media.isReferenceItemNameVisible(firstMediaFileName);
|
||||
await umbracoUi.media.isReferenceItemNameVisible(secondMediaFileName);
|
||||
await umbracoUi.media.clickConfirmTrashButton();
|
||||
|
||||
// Assert
|
||||
await umbracoUi.media.isSuccessNotificationVisible();
|
||||
expect(await umbracoApi.media.doesNameExist(firstMediaFileName)).toBeFalsy();
|
||||
expect(await umbracoApi.media.doesNameExist(secondMediaFileName)).toBeFalsy();
|
||||
expect(await umbracoApi.media.doesMediaItemExistInRecycleBin(firstMediaFileName)).toBeTruthy();
|
||||
expect(await umbracoApi.media.doesMediaItemExistInRecycleBin(secondMediaFileName)).toBeTruthy();
|
||||
await umbracoUi.media.isItemVisibleInRecycleBin(firstMediaFileName);
|
||||
await umbracoUi.media.isItemVisibleInRecycleBin(secondMediaFileName, true, false);
|
||||
|
||||
// Clean
|
||||
await umbracoApi.media.ensureNameNotExists(firstMediaFileName);
|
||||
await umbracoApi.media.ensureNameNotExists(secondMediaFileName);
|
||||
await umbracoApi.document.ensureNameNotExists(documentPickerName1[0]);
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentPickerName1[1]);
|
||||
await umbracoApi.document.ensureNameNotExists(documentPickerName2[0]);
|
||||
await umbracoApi.documentType.ensureNameNotExists(documentPickerName2[1]);
|
||||
await umbracoApi.media.emptyRecycleBin();
|
||||
});
|
||||
Reference in New Issue
Block a user