Forward merge v11/dev to v12/dev (#13509)

* update marketplace url to its final, live url

* Added various Block Grid translations (EN & NL) (#13488)

* Added various translations

* Added another translation

* Change request

* Revert breaking changes adding IContextCache to deploy connectors (#13489)

* Remove breaking changes in Deploy connector interfaces

* Add extension methods for calling the new interface methods in a backwards-compatible way

* Create and pack empty file to add TFM dependency (#13475)

* Change login image to new SVG. (#13493)

* Only add global usings when ImplicitUsings is enabled (#13491)

* bump to rc6

* V11: Allow changing logging directory from configuration (#13485)

* Allow changing logging directory from configuration

* Clean up

* Missing return statement

* Apply suggestions from code review

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>

* Update src/Umbraco.Core/Constants-SystemDirectories.cs

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>

* Move login.svg file

* Make sure contexbar fits within the available space (#13467)

* Make sure contexbar fits within the available space

* Ensuring context bar moves above, no matter size of it.

* Fixing apperance of connection-fixers

* Info panes not loading prerequisites (#13486)

* load relations immediately on init and remove call to non-existing function `appTabChange` on destroy

* load relations immediately on init and remove now not-used eventsService

* do not set layout gaps (#13496)

* Nuget updates (#13478)

* Updated nuget packages

* Remove npoco update

Co-authored-by: nikolajlauridsen <nikolajlauridsen@protonmail.ch>

* Nuget updates (#13478)

* Updated nuget packages

* Remove npoco update

Co-authored-by: nikolajlauridsen <nikolajlauridsen@protonmail.ch>

* Bump version to final

* V11/cherry pick flaky test (#13506)

* V10/feature/fixing flaky acceptance test (#13473)

* Bumped version

* Handle external authentication providers (#13487)

Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Co-authored-by: Corné Hoskam <choskam@hotmail.com>
Co-authored-by: Ronald Barendse <ronald@barend.se>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
Co-authored-by: Bjarke Berg <mail@bergmania.dk>
Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>
Co-authored-by: nikolajlauridsen <nikolajlauridsen@protonmail.ch>
Co-authored-by: Andreas Zerbst <73799582+andr317c@users.noreply.github.com>
This commit is contained in:
Kenn Jacobsen
2022-12-01 12:50:28 +01:00
committed by GitHub
parent 1875568e0b
commit 0b95d5e1e5
49 changed files with 827 additions and 383 deletions

View File

@@ -8,7 +8,7 @@
"hasInstallScript": true,
"dependencies": {
"@umbraco/json-models-builders": "^1.0.2",
"@umbraco/playwright-testhelpers": "^1.0.18",
"@umbraco/playwright-testhelpers": "^1.0.19",
"camelize": "^1.0.0",
"dotenv": "^16.0.2",
"faker": "^4.1.0",
@@ -138,9 +138,9 @@
}
},
"node_modules/@umbraco/playwright-testhelpers": {
"version": "1.0.18",
"resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.18.tgz",
"integrity": "sha512-SLtZqs3IxtuBfKBp25ZgAxjrXTIoR/mWQ8qfEFTpsebdQcnZVXxPXbCe2CwPT3zdTpjdjdh/HOfn/ONjtpL8Cw==",
"version": "1.0.19",
"resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.19.tgz",
"integrity": "sha512-NLZHRrWkfjzLoBc6RagQkbggT1awYARlmHNw50Aih566o+BnzkZ3usW0J8bvU4rW+8BbkClvOqUDCOP5vSYbVA==",
"dependencies": {
"@umbraco/json-models-builders": "^1.0.2",
"camelize": "^1.0.0",
@@ -1064,9 +1064,9 @@
}
},
"@umbraco/playwright-testhelpers": {
"version": "1.0.18",
"resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.18.tgz",
"integrity": "sha512-SLtZqs3IxtuBfKBp25ZgAxjrXTIoR/mWQ8qfEFTpsebdQcnZVXxPXbCe2CwPT3zdTpjdjdh/HOfn/ONjtpL8Cw==",
"version": "1.0.19",
"resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.19.tgz",
"integrity": "sha512-NLZHRrWkfjzLoBc6RagQkbggT1awYARlmHNw50Aih566o+BnzkZ3usW0J8bvU4rW+8BbkClvOqUDCOP5vSYbVA==",
"requires": {
"@umbraco/json-models-builders": "^1.0.2",
"camelize": "^1.0.0",

View File

@@ -20,7 +20,7 @@
},
"dependencies": {
"@umbraco/json-models-builders": "^1.0.2",
"@umbraco/playwright-testhelpers": "^1.0.18",
"@umbraco/playwright-testhelpers": "^1.0.19",
"camelize": "^1.0.0",
"faker": "^4.1.0",
"form-data": "^4.0.0",

View File

@@ -553,8 +553,9 @@ test.describe('Content tests', () => {
// Save and publish
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish));
await umbracoUi.isSuccessNotificationVisible();
// Added additional time because it could fail on pipeline because it's not saving fast enough
await umbracoUi.isSuccessNotificationVisible({timeout:20000});
// Assert
const expectedContent = '<p>Acceptance test</p>'
await expect(await umbracoApi.content.verifyRenderedContent('/contentpickercontent', expectedContent, true)).toBeTruthy();

View File

@@ -15,7 +15,7 @@ test.describe('System Information', () => {
await umbracoApi.users.setCurrentLanguage(enCulture);
});
async function openSystemInformation(page: Page, umbracoUi : UiHelpers) {
async function openSystemInformation(page: Page, umbracoUi: UiHelpers) {
//We have to wait for page to load, if the site is slow
await umbracoUi.clickElement(umbracoUi.getGlobalHelp());
await expect(page.locator('.umb-help-list-item').last()).toBeVisible();
@@ -47,4 +47,4 @@ test.describe('System Information', () => {
// Close the help panel
await page.locator('.umb-button__content').last().click();
});
});
});

View File

@@ -1,70 +1,69 @@
import {expect } from '@playwright/test';
import {test} from "@umbraco/playwright-testhelpers";
test.describe('Login', () => {
test.beforeEach(async ({ page, umbracoApi }, testInfo) => {
await umbracoApi.report.report(testInfo);
await page.goto(process.env.URL + '/umbraco');
});
test('Login with correct username and password', async ({page}) => {
test.beforeEach(async ({ page, umbracoApi }, testInfo) => {
await umbracoApi.report.report(testInfo);
await page.goto(process.env.URL + '/umbraco');
});
test('Login with correct username and password', async ({page}) => {
let error = page.locator('.text-error');
await expect(error).toBeHidden();
let error = page.locator('.text-error');
await expect(error).toBeHidden();
// Action
await page.fill('#umb-username', process.env.UMBRACO_USER_LOGIN);
await page.fill('#umb-passwordTwo', process.env.UMBRACO_USER_PASSWORD);
await page.locator('[label-key="general_login"]').click();
await page.waitForNavigation();
// Action
await page.fill('#umb-username', process.env.UMBRACO_USER_LOGIN);
await page.fill('#umb-passwordTwo', process.env.UMBRACO_USER_PASSWORD);
await page.locator('[label-key="general_login"]').click();
await page.waitForNavigation();
// Assert
await expect(page).toHaveURL(process.env.URL + '/umbraco#/content');
let usernameField = await page.locator('#umb-username');
let passwordField = await page.locator('#umb-passwordTwo');
await expect(usernameField).toHaveCount(0);
await expect(passwordField).toHaveCount(0);
});
// Assert
await expect(page).toHaveURL(process.env.URL + '/umbraco#/content');
let usernameField = await page.locator('#umb-username');
let passwordField = await page.locator('#umb-passwordTwo');
await expect(usernameField).toHaveCount(0);
await expect(passwordField).toHaveCount(0);
});
test('Login with correct username but wrong password', async({page}) => {
const username = process.env.UMBRACO_USER_LOGIN;
const password = 'wrong';
test('Login with correct username but wrong password', async ({page}) => {
const username = process.env.UMBRACO_USER_LOGIN;
const password = 'wrong';
// Precondition
let error = page.locator('.text-error');
await expect(error).toBeHidden();
// Precondition
let error = page.locator('.text-error');
await expect(error).toBeHidden();
// Action
await page.fill('#umb-username', username);
await page.fill('#umb-passwordTwo', password);
await page.locator('[label-key="general_login"]').click();
// Action
await page.fill('#umb-username', username);
await page.fill('#umb-passwordTwo', password);
await page.locator('[label-key="general_login"]').click();
// Assert
let usernameField = await page.locator('#umb-username');
let passwordField = await page.locator('#umb-passwordTwo');
await expect(error).toBeVisible();
await expect(usernameField).toBeVisible();
await expect(passwordField).toBeVisible();
});
// Assert
let usernameField = await page.locator('#umb-username');
let passwordField = await page.locator('#umb-passwordTwo');
await expect(error).toBeVisible();
await expect(usernameField).toBeVisible();
await expect(passwordField).toBeVisible();
});
test('Login with wrong username and wrong password', async({page}) => {
const username = 'wrong-username';
const password = 'wrong';
test('Login with wrong username and wrong password', async ({page}) => {
const username = 'wrong-username';
const password = 'wrong';
// Precondition
let error = page.locator('.text-error');
await expect(error).toBeHidden();
// Precondition
let error = page.locator('.text-error');
await expect(error).toBeHidden();
// Action
await page.fill('#umb-username', username);
await page.fill('#umb-passwordTwo', password);
await page.locator('[label-key="general_login"]').click();
// Action
await page.fill('#umb-username', username);
await page.fill('#umb-passwordTwo', password);
await page.locator('[label-key="general_login"]').click();
// Assert
let usernameField = await page.locator('#umb-username');
let passwordField = await page.locator('#umb-passwordTwo');
await expect(error).toBeVisible();
await expect(usernameField).toBeVisible();
await expect(passwordField).toBeVisible();
});
// Assert
let usernameField = await page.locator('#umb-username');
let passwordField = await page.locator('#umb-passwordTwo');
await expect(error).toBeVisible();
await expect(usernameField).toBeVisible();
await expect(passwordField).toBeVisible();
});
});

View File

@@ -53,7 +53,7 @@ test.describe('Media', () => {
// Assert
// Needs to wait before refreshing the media tree, otherwise the media files wont be moved to the folder yet
await page.waitForTimeout(1000);
await page.waitForTimeout(2500);
await umbracoUi.refreshMediaTree();
await page.locator('[data-element="tree-item-' + folderToMoveTooName + '"]').click();
for (const names of mediaFileTypes) {

View File

@@ -32,8 +32,8 @@ test.describe('Modelsbuilder tests', () => {
.done()
.done()
.build();
await umbracoApi.documentTypes.save(docType);
await umbracoApi.templates.edit(docTypeName, `@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.Testdocument>
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@@ -47,9 +47,9 @@ test.describe('Modelsbuilder tests', () => {
await umbracoUi.createContentWithDocumentType(docTypeName);
await umbracoUi.setEditorHeaderName(contentName);
// Fortunately for us the input field of a text box has the alias of the property as an id :)
await page.locator("#title").type("Hello world!")
await page.locator("#title").type("Hello world!");
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish));
await umbracoUi.isSuccessNotificationVisible();
await umbracoUi.isSuccessNotificationVisible({timeout:10000});
// Ensure that we can render it on the frontend = we can compile the models and views
await umbracoApi.content.verifyRenderedContent("/", "<h1>Hello world!</h1>", true);
@@ -62,7 +62,7 @@ test.describe('Modelsbuilder tests', () => {
const docTypeName = "TestDocument";
const docTypeAlias = AliasHelper.toAlias(docTypeName);
const propertyAlias = "title";
const propertyValue = "Hello world!"
const propertyValue = "Hello world!";
await umbracoApi.content.deleteAllContent();
await umbracoApi.documentTypes.ensureNameNotExists(docTypeName);
@@ -80,8 +80,8 @@ test.describe('Modelsbuilder tests', () => {
.done()
.done()
.build();
const savedDocType = await umbracoApi.documentTypes.save(docType);
await umbracoApi.templates.edit(docTypeName, `@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.Testdocument>
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@@ -90,7 +90,6 @@ test.describe('Modelsbuilder tests', () => {
}
<h1>@Model.Title</h1>`);
const content = new ContentBuilder()
.withContentTypeAlias(savedDocType["alias"])
.withAction("publishNew")
@@ -104,7 +103,6 @@ test.describe('Modelsbuilder tests', () => {
.done()
.done()
.build()
await umbracoApi.content.save(content);
// Navigate to the document type
@@ -118,7 +116,8 @@ test.describe('Modelsbuilder tests', () => {
await page.locator('.umb-card-grid >> [title="Textstring"]').click();
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.submit));
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save));
await umbracoUi.isSuccessNotificationVisible();
// Has a long timeout because it can sometimes take longer than 5 sec to save on the pipeline
await umbracoUi.isSuccessNotificationVisible({timeout:10000});
// Now that the content is updated and the models are rebuilt, ensure that we can still render the frontend.
await umbracoApi.content.verifyRenderedContent("/", "<h1>" + propertyValue + "</h1>", true)
@@ -132,7 +131,7 @@ test.describe('Modelsbuilder tests', () => {
const docTypeName = "TestDocument";
const docTypeAlias = AliasHelper.toAlias(docTypeName);
const propertyAlias = "title";
const propertyValue = "Hello world!"
const propertyValue = "Hello world!";
await umbracoApi.content.deleteAllContent();
await umbracoApi.documentTypes.ensureNameNotExists(docTypeName);
@@ -150,8 +149,8 @@ test.describe('Modelsbuilder tests', () => {
.done()
.done()
.build();
const savedDocType = await umbracoApi.documentTypes.save(docType);
await umbracoApi.templates.edit(docTypeName, `@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.Testdocument>
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@@ -173,8 +172,7 @@ test.describe('Modelsbuilder tests', () => {
.withValue(propertyValue)
.done()
.done()
.build()
.build();
await umbracoApi.content.save(content);
// Navigate to the document type
@@ -183,11 +181,12 @@ test.describe('Modelsbuilder tests', () => {
const editor = await page.locator('.ace_content');
await editor.click();
// We only have to type out the opening tag, the editor adds the closing tag automatically.
await editor.type("<p>Edited")
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save))
await editor.type("<p>Edited");
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save));
await umbracoUi.isSuccessNotificationVisible({timeout:10000});
await umbracoUi.isSuccessNotificationVisible();
await umbracoApi.content.verifyRenderedContent("/", "<h1>" + propertyValue + "</h1><p>Edited</p>", true)
await umbracoApi.content.verifyRenderedContent("/", "<h1>" + propertyValue + "</h1><p>Edited</p>", true);
await umbracoApi.content.deleteAllContent();
await umbracoApi.documentTypes.ensureNameNotExists(docTypeName);
@@ -198,7 +197,7 @@ test.describe('Modelsbuilder tests', () => {
const docTypeName = "TestDocument";
const docTypeAlias = AliasHelper.toAlias(docTypeName);
const propertyAlias = "title";
const propertyValue = "Hello world!"
const propertyValue = "Hello world!";
const contentName = "Home";
await umbracoApi.content.deleteAllContent();
@@ -217,8 +216,8 @@ test.describe('Modelsbuilder tests', () => {
.done()
.done()
.build();
const savedDocType = await umbracoApi.documentTypes.save(docType);
await umbracoApi.templates.edit(docTypeName, `@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.Testdocument>
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@@ -240,8 +239,7 @@ test.describe('Modelsbuilder tests', () => {
.withValue(propertyValue)
.done()
.done()
.build()
.build();
await umbracoApi.content.save(content);
// Navigate to the document type
@@ -263,9 +261,9 @@ test.describe('Modelsbuilder tests', () => {
const editor = await page.locator('.ace_content');
await editor.click();
// We only have to type out the opening tag, the editor adds the closing tag automatically.
await editor.type("<p>@Model.Bod")
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save))
await umbracoUi.isSuccessNotificationVisible();
await editor.type("<p>@Model.Bod");
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save));
await umbracoUi.isSuccessNotificationVisible({timeout: 10000});
await page.locator('span:has-text("×")').click();
// Navigate to the content section and update the content
@@ -273,12 +271,12 @@ test.describe('Modelsbuilder tests', () => {
await umbracoUi.refreshContentTree();
await umbracoUi.clickElement(umbracoUi.getTreeItem("content", [contentName]));
await page.locator("#bod").type("Fancy body text");
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish))
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish));
await umbracoApi.content.verifyRenderedContent("/", "<h1>" + propertyValue + "</h1><p>Fancy body text</p>", true);
await umbracoApi.content.deleteAllContent();
await umbracoApi.documentTypes.ensureNameNotExists(docTypeName);
await umbracoApi.templates.ensureNameNotExists(docTypeName)
await umbracoApi.templates.ensureNameNotExists(docTypeName);
});
});

View File

@@ -37,8 +37,8 @@ test.describe('Packages', () => {
.withContentTypeAlias(rootDocTypeAlias)
.withAction("saveNew")
.addVariant()
.withName(nodeName)
.withSave(true)
.withName(nodeName)
.withSave(true)
.done()
.build();
const generatedContent = await umbracoApi.content.save(rootContentNode);
@@ -116,8 +116,12 @@ test.describe('Packages', () => {
// Navigate to create package section
await umbracoUi.goToSection(ConstantHelper.sections.packages);
await page.locator('[data-element="sub-view-umbCreatedPackages"]').click()
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.delete));
await page.waitForTimeout(100);
// Selects the correct package
await page.locator('text=' + packageName + ' Delete >> button').click();
// Waits until the selector is visible
await expect(page.locator('[label-key="contentTypeEditor_yesDelete"]')).toBeVisible();
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey('contentTypeEditor_yesDelete'));
// Assert
@@ -126,7 +130,6 @@ test.describe('Packages', () => {
// Cleanup
await umbracoApi.content.deleteAllContent();
await umbracoApi.documentTypes.ensureNameNotExists(rootDocTypeName);
await umbracoApi.packages.ensureNameNotExists(packageName);
});
test('Download package', async ({page, umbracoApi, umbracoUi}) => {

View File

@@ -10,13 +10,13 @@ test.describe('Macros', () => {
test('Create macro', async ({ page, umbracoApi, umbracoUi }) => {
const name = "Test macro";
const partialViewName = "Test partialView";
const partialViewMacroFileName = "Test_partialView";
await umbracoApi.macros.ensureNameNotExists(name);
await umbracoApi.partialViews.ensureMacroFileNameNotExists(partialViewName);
await umbracoApi.partialViews.ensureMacroFileNameNotExists(partialViewMacroFileName + ".cshtml");
const partialViewMacro = new PartialViewMacroBuilder()
.withName(partialViewName)
.withName(partialViewMacroFileName)
.withContent("@inherits Umbraco.Web.Macros.PartialViewMacroPage")
.build();
await umbracoApi.partialViews.save(partialViewMacro);
@@ -32,7 +32,7 @@ test.describe('Macros', () => {
// Adds partial view to macro
await page.locator('[data-element="property-label-macroPartialViewPickerProperty"]').click();
await page.locator('[data-element="tree-item-' + partialViewName + '.cshtml"]').click();
await page.locator('[data-element="tree-item-' + partialViewMacroFileName + '.cshtml"]').click();
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save));
@@ -41,6 +41,6 @@ test.describe('Macros', () => {
// Clean up
await umbracoApi.macros.ensureNameNotExists(name);
await umbracoApi.partialViews.ensureMacroFileNameNotExists(partialViewName);
await umbracoApi.partialViews.ensureMacroFileNameNotExists(partialViewMacroFileName + ".cshtml");
});
});

View File

@@ -3,10 +3,18 @@ import {ConstantHelper, test} from '@umbraco/playwright-testhelpers';
import {TemplateBuilder} from "@umbraco/json-models-builders";
test.describe('Templates', () => {
const name = 'Templatetest';
test.beforeEach(async ({ page, umbracoApi }, testInfo) => {
await umbracoApi.report.report(testInfo);
await umbracoApi.login();
await umbracoApi.templates.ensureNameNotExists(name);
});
test.afterEach(async ({page, umbracoApi}) => {
await umbracoApi.templates.ensureNameNotExists(name);
})
async function navigateToSettings(page, umbracoUi) {
await umbracoUi.goToSection(ConstantHelper.sections.settings);
@@ -15,67 +23,58 @@ test.describe('Templates', () => {
async function createTemplate(page, umbracoUi) {
await navigateToSettings(page, umbracoUi);
await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["Templates"]), {button: "right"});
await umbracoUi.clickDataElementByElementName('tree-item-templates', {button: "right"});
await umbracoUi.clickElement(umbracoUi.getContextMenuAction(ConstantHelper.actions.create));
}
test('Create template', async ({page, umbracoApi, umbracoUi}) => {
const name = "Create template test";
await umbracoApi.templates.ensureNameNotExists(name);
await createTemplate(page, umbracoUi);
// We have to wait for the ace editor to load, because when the editor is loading it will "steal" the focus briefly,
// which causes the save event to fire if we've added something to the header field, causing errors.
await page.waitForTimeout(500);
// Type name
await umbracoUi.getEditorHeaderName(name)
await umbracoUi.getEditorHeaderName(name);
// Save
// We must drop focus for the auto save event to occur.
await page.focus('.btn-success');
// And then wait for the auto save event to finish by finding the page in the tree view.
// This is a bit of a roundabout way to find items in a tree view since we dont use umbracoTreeItem
// but we must be able to wait for the save event to finish, and we can't do that with umbracoTreeItem
const label = await page.locator("a:has-text('Create template test')");
await expect(label).toBeVisible({timeout: 10000});
await expect(page.locator('[data-element="tree-item-' + name + '"]')).toBeVisible({timeout: 10000});
// Now that the auto save event has finished we can save
// and there wont be any duplicates or file in use errors.
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save));
//Assert
// Assert
await umbracoUi.isSuccessNotificationVisible();
// For some reason cy.umbracoErrorNotification tries to click the element which is not possible
// if it doesn't actually exist, making should('not.be.visible') impossible.
await expect(await page.locator('.umb-notifications__notifications > .alert-error')).not.toBeVisible();
// Clean up
await umbracoApi.templates.ensureNameNotExists(name);
});
test('Unsaved changes stay', async ({page, umbracoApi, umbracoUi}) => {
const name = "Templates Unsaved Changes Stay test";
const edit = "var num = 5;";
await umbracoApi.templates.ensureNameNotExists(name);
const template = new TemplateBuilder()
.withName(name)
.withContent('@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage\n')
.build();
await umbracoApi.templates.saveTemplate(template);
await navigateToSettings(page, umbracoUi);
await umbracoUi.navigateToTemplate(name);
// Open partial view
await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["Templates", name]));
// Edit
// We select the template so it does not auto save.
await page.locator('.ace_content').click();
await page.waitForTimeout(1000);
await page.locator('.ace_content').type(edit);
await expect(await page.locator('.ace_content')).toBeVisible();
await expect(await page.locator('.btn-success')).toBeVisible();
// Navigate away
await umbracoUi.goToSection(ConstantHelper.sections.content);
await umbracoUi.waitForTreeLoad(ConstantHelper.sections.content);
// Click stay button
await page.locator('umb-button[label="Stay"] button:enabled').click();
@@ -83,29 +82,23 @@ test.describe('Templates', () => {
// That the same document is open
await expect(await page.locator('#headerName')).toHaveValue(name);
await expect(await page.locator('.ace_content')).toContainText(edit);
// Clean up
await umbracoApi.templates.ensureNameNotExists(name);
});
test('Discard unsaved changes', async ({page, umbracoApi, umbracoUi}) => {
const name = "Discard changes test";
const edit = "var num = 5;";
await umbracoApi.templates.ensureNameNotExists(name);
const template = new TemplateBuilder()
.withName(name)
.withContent('@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage\n')
.build();
await umbracoApi.templates.saveTemplate(template);
await navigateToSettings(page, umbracoUi);
// Open partial view
await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["Templates", name]));
await umbracoUi.navigateToTemplate(name);
// Edit
// We select the template so it does not auto save.
await page.locator('.ace_content').click();
await page.waitForTimeout(1000);
await page.locator('.ace_content').type(edit);
await expect(await page.locator('.ace_content')).toBeVisible();
await expect(await page.locator('.btn-success')).toBeVisible();
@@ -120,27 +113,20 @@ test.describe('Templates', () => {
// Asserts
await expect(await page.locator('.ace_content')).not.toContainText(edit);
// cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.false; }); TODO: Switch to template
await umbracoApi.templates.ensureNameNotExists(name);
});
test('Insert macro', async ({page, umbracoApi, umbracoUi}) => {
const name = 'InsertMacroTest';
await umbracoApi.templates.ensureNameNotExists(name);
await umbracoApi.macros.ensureNameNotExists(name);
const template = new TemplateBuilder()
.withName(name)
.withContent('')
.build();
await umbracoApi.templates.saveTemplate(template);
await umbracoApi.macros.save(name);
await navigateToSettings(page, umbracoUi);
await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["Templates", name]));
await umbracoUi.navigateToTemplate(name);
// Insert macro
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.insert));
@@ -151,24 +137,17 @@ test.describe('Templates', () => {
await expect(await page.locator('.ace_content')).toContainText('@await Umbraco.RenderMacroAsync("' + name + '")');
// Clean
await umbracoApi.templates.ensureNameNotExists(name);
await umbracoApi.macros.ensureNameNotExists(name);
});
});
test('Insert value', async ({page, umbracoApi, umbracoUi}) => {
const name = 'Insert Value Test';
await umbracoApi.templates.ensureNameNotExists(name);
const partialView = new TemplateBuilder()
.withName(name)
.withContent('')
.build();
await umbracoApi.templates.saveTemplate(partialView);
await navigateToSettings(page, umbracoUi);
await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["Templates", name]));
await umbracoUi.navigateToTemplate(name);
// Insert value
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.insert));
@@ -177,10 +156,7 @@ test.describe('Templates', () => {
await page.selectOption('select', 'umbracoBytes');
await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.submit));
// assert
// Assert
await expect(await page.locator('.ace_content')).toContainText('@Model.Value("umbracoBytes")');
// Clean
await umbracoApi.templates.ensureNameNotExists(name);
});
});
});

View File

@@ -11,9 +11,9 @@
<ItemGroup>
<PackageReference Include="Bogus" Version="34.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" PrivateAssets="all" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" PrivateAssets="all" />
</ItemGroup>
<Import Project="..\..\src\Umbraco.Cms.Targets\buildTransitive\Umbraco.Cms.Targets.props" />

View File

@@ -305,7 +305,7 @@ public class UdiTests
}
[UdiDefinition("foo", UdiType.GuidUdi)]
public class FooConnector : IServiceConnector
public class FooConnector : IServiceConnector2
{
public IArtifact GetArtifact(Udi udi, IContextCache contextCache) => throw new NotImplementedException();

View File

@@ -8,8 +8,8 @@
<ItemGroup>
<PackageReference Include="AngleSharp" Version="0.17.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
<PackageReference Include="System.Data.Odbc" Version="7.0.0" />
<PackageReference Include="System.Data.OleDb" Version="7.0.0" />
</ItemGroup>