Merge branch 'v9/contrib' into v9/dev

# Conflicts:
#	src/Umbraco.Web.UI.Client/src/common/directives/components/localization/localize.directive.js
#	src/Umbraco.Web.UI/umbraco/config/lang/en.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
#	tests/Umbraco.Tests.AcceptanceTest/cypress/integration/Languages/languages.ts
This commit is contained in:
Sebastiaan Janssen
2021-12-14 13:32:46 +01:00
43 changed files with 745 additions and 472 deletions

View File

@@ -1,16 +1,38 @@
/// <reference types="Cypress" />
context('Languages', () => {
beforeEach(() => {
cy.umbracoLogin(Cypress.env('username'), Cypress.env('password'), false);
});
it('Creates language', () => {
// Setup
const language = 'Danish';
const culture = 'da';
cy.umbracoEnsureLanguageCultureNotExists(culture);
cy.umbracoSection('settings');
// Enter language tree and create new language
cy.umbracoTreeItem('settings', ['Languages']).click();
cy.umbracoButtonByLabelKey('languages_addLanguage').click();
cy.get('select[name="newLang"]').select(language);
// Save and assert success
cy.umbracoButtonByLabelKey('buttons_save').click();
cy.umbracoSuccessNotification().should('be.visible');
// Cleanup
cy.umbracoEnsureLanguageCultureNotExists(culture);
});
it('Deletes language', () => {
// Setup
const language1 = 'da';
const language2 = 'en-GB';
cy.umbracoEnsureLanguageNotExists(language1);
cy.umbracoEnsureLanguageNotExists(language2);
cy.umbracoEnsureLanguageCultureNotExists(language1);
cy.umbracoEnsureLanguageCultureNotExists(language2);
cy.umbracoCreateLanguage(language1, true, '1');
cy.umbracoCreateLanguage(language2, true, '1');
//Enter settings section and wait for everything to load
@@ -32,8 +54,8 @@ context('Languages', () => {
cy.get('tbody > tr').should('have.length', 2);
// Cleanup
cy.umbracoEnsureLanguageNotExists(language1);
cy.umbracoEnsureLanguageNotExists(language2);
cy.umbracoEnsureLanguageCultureNotExists(language1);
cy.umbracoEnsureLanguageCultureNotExists(language2);
});
});

View File

@@ -16,7 +16,7 @@ context('Media Types', () => {
cy.umbracoTreeItem("settings", ["Media Types"]).rightclick();
cy.umbracoContextMenuAction("action-create").click();
cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click();
cy.get('.menu-label localize[key="content_mediatype"]').click();
//Type name

View File

@@ -29,7 +29,7 @@ context('Partial View Macro Files', () => {
openPartialViewMacroCreatePanel();
cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-label").click();
cy.get('.menu-label localize[key="create_newPartialViewMacro"]').click();
//Type name
cy.umbracoEditorHeaderName(name);

View File

@@ -26,7 +26,7 @@ context('Partial Views', () => {
openPartialViewsCreatePanel();
cy.umbracoContextMenuAction("action-create").click();
cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click();
cy.get('.menu-label localize[key="create_newEmptyPartialView"]').click();
//Type name
cy.umbracoEditorHeaderName(name);
@@ -73,7 +73,7 @@ context('Partial Views', () => {
openPartialViewsCreatePanel();
cy.umbracoContextMenuAction("action-create").click();
cy.get('.menu-label').first().click();
cy.get('.menu-label localize[key="create_newEmptyPartialView"]').click();
// The test would fail intermittently, most likely because the editor didn't have time to load
// This should ensure that the editor is loaded and the test should no longer fail unexpectedly.

View File

@@ -23,7 +23,7 @@ context('Scripts', () => {
cy.umbracoTreeItem("settings", ["Scripts"]).rightclick();
cy.umbracoContextMenuAction("action-create").click();
cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click();
cy.get('.menu-label localize[key="create_newJavascriptFile"]').click();
//We have to wait here till everything is loaded, or worker will throw error
cy.intercept('/umbraco/lib/ace-builds/src-min-noconflict/worker-javascript.js').as('aceWorker');
cy.wait('@aceWorker');

View File

@@ -1,15 +1,21 @@
/// <reference types="Cypress" />
context('Stylesheets', () => {
const name = "TestStylesheet";
const fileName = name + ".css";
beforeEach(() => {
cy.umbracoLogin(Cypress.env('username'), Cypress.env('password'));
cy.umbracoEnsureStylesheetNameNotExists(fileName);
});
afterEach(() => {
// Clean up, this ensures that even if tests break we clean up
cy.umbracoEnsureStylesheetNameNotExists(fileName);
});
it('Create new style sheet file', () => {
const name = "TestStylesheet";
const fileName = name + ".css";
cy.umbracoEnsureStylesheetNameNotExists(fileName);
cy.umbracoSection('settings');
cy.get('li .umb-tree-root:contains("Settings")').should("be.visible");
@@ -17,21 +23,52 @@ context('Stylesheets', () => {
cy.umbracoTreeItem("settings", ["Stylesheets"]).rightclick();
cy.umbracoContextMenuAction("action-create").click();
cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click();
//We have to wait here till everything is loaded, or worker will throw error
cy.get('.menu-label').first().click(); // TODO: Would be better to use something like cy.umbracoContextMenuAction("action-mediaType").click();
// We have to wait here till everything is loaded, or worker will throw error
cy.intercept('/umbraco/lib/ace-builds/src-min-noconflict/worker-css.js').as('aceWorker');
cy.wait('@aceWorker');
//Type name
// Type name
cy.umbracoEditorHeaderName(name);
//Save
// Save
cy.get('.btn-success').click();
//Assert
// Assert
cy.umbracoSuccessNotification().should('be.visible');
//Clean up
cy.umbracoEnsureStylesheetNameNotExists(fileName);
});
it('Deletes a stylesheet', () => {
var stylesheetData = {
"virtualPath": "/css/",
"path": null,
"name": name,
"content": "",
"fileType": "stylesheets",
"snippet": null,
"id": "0",
"notifications": []
}
let url = '/umbraco/backoffice/umbracoapi/codefile/PostSave'
cy.umbracoApiRequest(url, 'POST', stylesheetData);
// Navigate to Settings section
cy.umbracoSection('settings');
cy.get('li .umb-tree-root:contains("Settings")').should("be.visible");
// Open stylesheet tree
cy.get('[data-element="tree-item-stylesheets"] > .umb-tree-item__inner > .umb-tree-item__arrow').click();
// Delete stylesheet
cy.get('.umb-tree-item__inner > .umb-tree-item__label').contains(name).rightclick();
cy.get('.umb-action-link').click();
cy.get('[ng-if="showConfirm"]').click();
// Assert
cy.get('.umb-tree-item__inner > .umb-tree-item__label').contains(name).should('not.exist');
});
});

View File

@@ -1,13 +1,40 @@
/// <reference types="Cypress" />
context('Users', () => {
const name = "Alice Bobson";
const email = "alice-bobson@acceptancetest.umbraco";
const startContentIds = [];
const startMediaIds = [];
const userGroups = ["admin"];
const userData =
{
"id": -1,
"parentId": -1,
"name": name,
"username": email,
"culture": "en-US",
"email": email,
"startContentIds": startContentIds,
"startMediaIds": startMediaIds,
"userGroups": userGroups,
"message": ""
};
beforeEach(() => {
cy.umbracoLogin(Cypress.env('username'), Cypress.env('password'));
});
afterEach(() => {
//Clean up
cy.umbracoEnsureUserEmailNotExists(email);
});
function createUser(){
let url = '/umbraco/backoffice/umbracoapi/users/PostCreateUser';
cy.umbracoApiRequest(url, 'POST', userData);
}
it('Create user', () => {
const name = "Alice Bobson";
const email = "alice-bobson@acceptancetest.umbraco";
cy.umbracoEnsureUserEmailNotExists(email);
cy.umbracoSection('users');
@@ -24,55 +51,16 @@ context('Users', () => {
cy.get('.umb-button > .btn > .umb-button__content').click();
cy.umbracoButtonByLabelKey("user_goToProfile").should('be.visible');
//Clean up
cy.umbracoEnsureUserEmailNotExists(email);
});
it('Update user', () => {
// Set userdata
const name = "Alice Bobson";
const email = "alice-bobson@acceptancetest.umbraco";
const startContentIds = [];
const startMediaIds = [];
const userGroups = ["admin"];
var userData =
{
"id": -1,
"parentId": -1,
"name": name,
"username": email,
"culture": "en-US",
"email": email,
"startContentIds": startContentIds,
"startMediaIds": startMediaIds,
"userGroups": userGroups,
"message": ""
};
// Ensure user doesn't exist
cy.umbracoEnsureUserEmailNotExists(email);
// Create user through API
cy.getCookie('UMB-XSRF-TOKEN', { log: false }).then((token) => {
cy.request({
method: 'POST',
url: '/umbraco/backoffice/umbracoapi/users/PostCreateUser',
followRedirect: true,
headers: {
Accept: 'application/json',
'X-UMB-XSRF-TOKEN': token.value,
},
body: userData,
log: false,
}).then((response) => {
return;
});
});
//Create user through API
createUser();
// Go to the user and edit their name
cy.umbracoSection('users');
@@ -82,50 +70,15 @@ context('Users', () => {
// assert save succeeds
cy.umbracoSuccessNotification().should('be.visible');
cy.umbracoEnsureUserEmailNotExists(email);
})
it('Delete user', () => {
// Set userdata
const name = "Alice Bobson";
const email = "alice-bobson@acceptancetest.umbraco";
const startContentIds = [];
const startMediaIds = [];
const userGroups = ["admin"];
var userData =
{
"id": -1,
"parentId": -1,
"name": name,
"username": email,
"culture": "en-US",
"email": email,
"startContentIds": startContentIds,
"startMediaIds": startMediaIds,
"userGroups": userGroups,
"message": ""
};
it('Delete user', () => {
// Ensure user doesn't exist
cy.umbracoEnsureUserEmailNotExists(email);
// Create user through API
cy.getCookie('UMB-XSRF-TOKEN', { log: false }).then((token) => {
cy.request({
method: 'POST',
url: '/umbraco/backoffice/umbracoapi/users/PostCreateUser',
followRedirect: true,
headers: {
Accept: 'application/json',
'X-UMB-XSRF-TOKEN': token.value,
},
body: userData,
log: false,
}).then((response) => {
return;
});
});
//Create user through API
createUser();
// Go to the user and delete them
cy.umbracoSection('users');
@@ -135,6 +88,5 @@ context('Users', () => {
// assert deletion succeeds
cy.umbracoSuccessNotification().should('be.visible');
cy.umbracoEnsureUserEmailNotExists(email);
})
});
});

View File

@@ -57,9 +57,8 @@ Cypress.Commands.add('umbracoCreateLanguage', (culture, isMandatory = false, fal
});
});
Cypress.Commands.add('umbracoEnsureLanguageNotExists', (culture) => {
Cypress.Commands.add('umbracoEnsureLanguageCultureNotExists', (culture) => {
cy.getCookie('UMB-XSRF-TOKEN', { log: false }).then((token) => {
console.log('hit commands')
cy.request({
method: 'GET',
url: '/umbraco/backoffice/umbracoapi/language/GetAllLanguages',

View File

@@ -3,3 +3,28 @@
// type definitions for custom commands like "createDefaultTodos"
// <reference types="support" />
export {};
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
interface Chainable<Subject> {
/**
* Checks to see if the language with specified culture does not exist
* If it does it will automatically delete it
* @param {string} culture Culture of language to delete
* @example cy.umbracoEnsureLanguageCultureNotExists('da-DK');
*/
umbracoEnsureLanguageCultureNotExists: (culture: string) => Chainable<void>;
/**
* Creates a language from a culture
* @param {string} culture Culture of the language - fx "da_DK"
* @param {boolean} isMandatory Set whether the language is mandatory or not. Defaults to false
* @param {string} fallbackLanguageId of the language to fallback to. Defaults to 1 which is en_US
* @example cy.umbracoCreateLanguage('da', true, '1');
*/
umbracoCreateLanguage: (culture: string, isMandatory: boolean, fallbackLanguageId: string) => Chainable<void>;
}
}
}