test: course creation flow
This commit is contained in:
@@ -1,133 +1,152 @@
|
|||||||
describe("Course Creation", () => {
|
describe("Course Creation", () => {
|
||||||
it("creates a new course", () => {
|
it("creates a new course", () => {
|
||||||
cy.login();
|
cy.login();
|
||||||
cy.visit("/courses");
|
cy.wait(1000);
|
||||||
|
|
||||||
|
cy.visit("/lms/courses");
|
||||||
|
|
||||||
// Create a course
|
// Create a course
|
||||||
cy.get("a.btn").contains("Create a Course").click();
|
cy.get("a").contains("New Course").click();
|
||||||
cy.wait(1000);
|
|
||||||
cy.url().should("include", "/courses/new-course/edit");
|
|
||||||
cy.get("#title").type("Test Course");
|
|
||||||
cy.get("#intro").type("Test Course Short Introduction");
|
|
||||||
cy.get("#description").type("Test Course Description");
|
|
||||||
cy.get("#video-link").type("-LPmw2Znl2c");
|
|
||||||
cy.get("#tags-input").type("Test");
|
|
||||||
cy.get("#published").check();
|
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
|
cy.url().should("include", "/courses/new/edit");
|
||||||
|
|
||||||
|
cy.get("label").contains("Title").type("Test Course");
|
||||||
|
cy.get("label")
|
||||||
|
.contains("Short Introduction")
|
||||||
|
.type("Test Course Short Introduction to test the UI");
|
||||||
|
cy.get("div[contenteditable=true").invoke(
|
||||||
|
"text",
|
||||||
|
"Test Course Description. I need a very big description to test the UI. This is a very big description. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now."
|
||||||
|
);
|
||||||
|
|
||||||
|
cy.fixture("profile.png", "base64").then((fileContent) => {
|
||||||
|
cy.get('input[type="file"]').attachFile({
|
||||||
|
fileContent,
|
||||||
|
fileName: "profile.png",
|
||||||
|
mimeType: "image/png",
|
||||||
|
encoding: "base64",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.get("label")
|
||||||
|
.contains("Preview Video")
|
||||||
|
.type("https://www.youtube.com/embed/-LPmw2Znl2c");
|
||||||
|
cy.get("[id=tags]").type("Learning{enter}Frappe{enter}ERPNext{enter}");
|
||||||
|
cy.get("label").contains("Published").click();
|
||||||
|
cy.get("label").contains("Published On").type("2021-01-01");
|
||||||
cy.button("Save").click();
|
cy.button("Save").click();
|
||||||
|
|
||||||
// Add Chapter
|
// Add Chapter
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.link("Course Outline").click();
|
cy.button("Add Chapter").click();
|
||||||
|
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.get(".edit-header .btn-add-chapter").click();
|
cy.get("[id^=headlessui-dialog-panel-")
|
||||||
cy.wait(500);
|
.should("be.visible")
|
||||||
cy.get("#chapter-title").type("Test Chapter");
|
.within(() => {
|
||||||
cy.get("#chapter-description").type("Test Chapter Description");
|
cy.get("label").contains("Title").type("Test Chapter");
|
||||||
cy.button("Save").click();
|
cy.button("Add Chapter").click();
|
||||||
|
});
|
||||||
|
|
||||||
// Add Lesson
|
// Add Lesson
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.link("Add Lesson").click();
|
cy.button("Add Lesson").click();
|
||||||
|
cy.wait(1000);
|
||||||
|
cy.url().should("include", "/learn/1-1/edit");
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.get("#lesson-title").type("Test Lesson");
|
|
||||||
|
|
||||||
// Content
|
cy.get("label").contains("Title").type("Test Lesson");
|
||||||
cy.get(".collapse-section.collapsed:first").click();
|
/* cy.get("#content .ce-block")
|
||||||
cy.get("#lesson-content .ce-block")
|
|
||||||
.click()
|
.click()
|
||||||
.type(
|
.invoke("text", "https://www.youtube.com/watch?v=GoDtyItReto"); */
|
||||||
|
/* cy.get("#content .ce-block")
|
||||||
|
.click()
|
||||||
|
.paste("https://www.youtube.com/watch?v=GoDtyItReto"); */
|
||||||
|
|
||||||
|
cy.fixture("Youtube.mov", "base64").then((fileContent) => {
|
||||||
|
cy.get('input[type="file"]').attachFile({
|
||||||
|
fileContent,
|
||||||
|
fileName: "Youtube.mov",
|
||||||
|
mimeType: "image/png",
|
||||||
|
encoding: "base64",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
cy.wait(1000);
|
||||||
|
cy.get("#content .ce-block").type(
|
||||||
"This is an extremely big paragraph that is meant to test the UI. This is a very long paragraph. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now. {enter}"
|
"This is an extremely big paragraph that is meant to test the UI. This is a very long paragraph. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now. {enter}"
|
||||||
);
|
);
|
||||||
cy.get("#lesson-content .ce-toolbar__plus").click();
|
|
||||||
cy.get('#lesson-content [data-item-name="youtube"]').click();
|
|
||||||
cy.get('input[data-fieldname="youtube"]').type("GoDtyItReto");
|
|
||||||
cy.button("Insert").click();
|
|
||||||
cy.wait(1000);
|
|
||||||
cy.button("Save").click();
|
cy.button("Save").click();
|
||||||
|
|
||||||
// View Course
|
// View Course
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.visit("/courses");
|
cy.visit("/lms");
|
||||||
cy.get(".course-card-title:first").contains("Test Course");
|
cy.wait(500);
|
||||||
cy.get(".course-card:first").click();
|
cy.url().should("include", "/lms/courses");
|
||||||
cy.url().should("include", "/courses/test-course");
|
cy.get(".grid a:first").within(() => {
|
||||||
cy.get("#title").contains("Test Course");
|
cy.get("div").contains("Test Course");
|
||||||
cy.get(".preview-video").should(
|
cy.get("div").contains(
|
||||||
|
"Test Course Short Introduction to test the UI"
|
||||||
|
);
|
||||||
|
cy.get(".course-image").should(
|
||||||
|
"have.css",
|
||||||
|
"background-image",
|
||||||
|
'url("/files/profile.png")'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
cy.get(".grid a:first").click();
|
||||||
|
cy.url().should("include", "/lms/courses/test-course");
|
||||||
|
cy.get("div").contains("Test Course");
|
||||||
|
cy.get("div").contains("Test Course Short Introduction to test the UI");
|
||||||
|
cy.get("div").contains("Learning");
|
||||||
|
cy.get("div").contains("Frappe");
|
||||||
|
cy.get("div").contains("ERPNext");
|
||||||
|
cy.get("iframe").should(
|
||||||
"have.attr",
|
"have.attr",
|
||||||
"src",
|
"src",
|
||||||
"https://www.youtube.com/embed/-LPmw2Znl2c"
|
"https://www.youtube.com/embed/-LPmw2Znl2c"
|
||||||
);
|
);
|
||||||
cy.get("#intro").contains("Test Course Short Introduction");
|
|
||||||
|
|
||||||
// View Chapter
|
// View Chapter
|
||||||
cy.get(".chapter-title-main:first").contains("Test Chapter");
|
cy.get("div").contains("Test Chapter");
|
||||||
cy.get(".chapter-description:first").contains(
|
cy.get("[id^=headlessui-disclosure-panel-").within(() => {
|
||||||
"Test Chapter Description"
|
cy.get("div").contains("Test Lesson").click();
|
||||||
);
|
});
|
||||||
cy.get(".lesson-info:first").contains("Test Lesson");
|
cy.wait(1000);
|
||||||
cy.get(".lesson-info:first").click();
|
|
||||||
|
|
||||||
// View Lesson
|
// View Lesson
|
||||||
cy.wait(1000);
|
cy.url().should("include", "/learn/1-1");
|
||||||
cy.url().should("include", "learn/1.1");
|
cy.get("div").contains("Test Lesson");
|
||||||
cy.get("#title").contains("Test Lesson");
|
cy.get("div").contains("Test User");
|
||||||
cy.get(".lesson-video iframe").should(
|
cy.get("div").contains(
|
||||||
"have.attr",
|
"This is an extremely big paragraph that is meant to test the UI. This is a very long paragraph. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now. "
|
||||||
"src",
|
|
||||||
"https://www.youtube.com/embed/GoDtyItReto"
|
|
||||||
);
|
|
||||||
cy.get(".lesson-content-card").contains(
|
|
||||||
"This is an extremely big paragraph that is meant to test the UI. This is a very long paragraph. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now."
|
|
||||||
);
|
);
|
||||||
|
cy.get("video")
|
||||||
|
.should("be.visible")
|
||||||
|
.children("source")
|
||||||
|
.should("have.attr", "src", "/files/Youtube.mov");
|
||||||
|
|
||||||
// Add Discussion
|
// Add Discussion
|
||||||
cy.get(".reply").click();
|
cy.button("New Question").click();
|
||||||
cy.wait(500);
|
cy.wait(500);
|
||||||
cy.get(".discussion-modal").should("be.visible");
|
cy.get("[id^=headlessui-dialog-panel-").within(() => {
|
||||||
|
cy.get("label").contains("Title").type("Test Discussion");
|
||||||
|
cy.get("div[contenteditable=true").invoke(
|
||||||
|
"text",
|
||||||
|
"This is a test discussion. This will check if the UI is working properly."
|
||||||
|
);
|
||||||
|
cy.button("Post").click();
|
||||||
|
});
|
||||||
|
|
||||||
// Enter title
|
// View Discussion
|
||||||
cy.get(".modal .topic-title")
|
cy.wait(500);
|
||||||
.type("Discussion from tests")
|
cy.get("div").contains("Test Discussion").click();
|
||||||
.should("have.value", "Discussion from tests");
|
cy.get("div[contenteditable=true").invoke(
|
||||||
|
"text",
|
||||||
// Enter comment
|
"This is a test comment. This will check if the UI is working properly."
|
||||||
cy.get(".modal .discussions-comment").type(
|
|
||||||
"This is a discussion from the cypress ui tests."
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Submit
|
cy.get("div").contains(
|
||||||
cy.get(".modal .submit-discussion").click();
|
"This is a test comment. This will check if the UI is working properly."
|
||||||
cy.wait(2000);
|
|
||||||
|
|
||||||
// Check if discussion is added to page and content is visible
|
|
||||||
cy.get(".sidebar-parent:first .discussion-topic-title").should(
|
|
||||||
"have.text",
|
|
||||||
"Discussion from tests"
|
|
||||||
);
|
|
||||||
cy.get(".sidebar-parent:first .discussion-topic-title").click();
|
|
||||||
cy.get(".discussion-on-page:visible").should("have.class", "show");
|
|
||||||
cy.get(
|
|
||||||
".discussion-on-page:visible .reply-card .reply-text .ql-editor p"
|
|
||||||
).should(
|
|
||||||
"have.text",
|
|
||||||
"This is a discussion from the cypress ui tests."
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.get(".discussion-form:visible .discussions-comment").type(
|
|
||||||
"This is a discussion from the cypress ui tests. \n\nThis comment was entered through the commentbox on the page."
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.get(".discussion-form:visible .submit-discussion").click();
|
|
||||||
cy.wait(3000);
|
|
||||||
cy.get(".discussion-on-page:visible").should("have.class", "show");
|
|
||||||
cy.get(".discussion-on-page:visible")
|
|
||||||
.children(".reply-card")
|
|
||||||
.eq(1)
|
|
||||||
.find(".reply-text")
|
|
||||||
.should(
|
|
||||||
"have.text",
|
|
||||||
"This is a discussion from the cypress ui tests. This comment was entered through the commentbox on the page.\n"
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
BIN
cypress/fixtures/Youtube.mov
Normal file
BIN
cypress/fixtures/Youtube.mov
Normal file
Binary file not shown.
BIN
cypress/fixtures/profile.png
Normal file
BIN
cypress/fixtures/profile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -24,6 +24,8 @@
|
|||||||
// -- This will overwrite an existing command --
|
// -- This will overwrite an existing command --
|
||||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||||
|
|
||||||
|
import "cypress-file-upload";
|
||||||
|
|
||||||
Cypress.Commands.add("login", (email, password) => {
|
Cypress.Commands.add("login", (email, password) => {
|
||||||
if (!email) {
|
if (!email) {
|
||||||
email = Cypress.config("testUser") || "Administrator";
|
email = Cypress.config("testUser") || "Administrator";
|
||||||
@@ -53,3 +55,13 @@ Cypress.Commands.add("iconButton", (text) => {
|
|||||||
Cypress.Commands.add("dialog", (selector) => {
|
Cypress.Commands.add("dialog", (selector) => {
|
||||||
return cy.get(`[role=dialog] ${selector}`);
|
return cy.get(`[role=dialog] ${selector}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("paste", { prevSubject: true }, (subject, text) => {
|
||||||
|
cy.wrap(subject).then(($element) => {
|
||||||
|
const element = $element[0];
|
||||||
|
element.focus();
|
||||||
|
element.textContent = text;
|
||||||
|
const event = new Event("paste", { bubbles: true });
|
||||||
|
element.dispatchEvent(event);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -147,8 +147,8 @@ const props = defineProps({
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: theme('colors.orange.100');
|
background-color: theme('colors.green.100');
|
||||||
color: theme('colors.orange.600');
|
color: theme('colors.green.600');
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-group {
|
.avatar-group {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
{{
|
{{
|
||||||
uploading
|
uploading
|
||||||
? __('Uploading {0}%').format(progress)
|
? __('Uploading {0}%').format(progress)
|
||||||
: __('Upload an File')
|
: __('Upload a File')
|
||||||
}}
|
}}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
size: '2xl',
|
size: '2xl',
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
label: 'Submit',
|
label: 'Post',
|
||||||
variant: 'solid',
|
variant: 'solid',
|
||||||
onClick: (close) => submitTopic(close),
|
onClick: (close) => submitTopic(close),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -114,7 +114,11 @@
|
|||||||
@click="removeTag(tag)"
|
@click="removeTag(tag)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<FormControl v-model="newTag" @keyup.enter="updateTags()" />
|
<FormControl
|
||||||
|
v-model="newTag"
|
||||||
|
@keyup.enter="updateTags()"
|
||||||
|
id="tags"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
<meta name="twitter:title" content="{{ meta.title }}" />
|
<meta name="twitter:title" content="{{ meta.title }}" />
|
||||||
<meta name="twitter:image" content="{{ meta.image }}" />
|
<meta name="twitter:image" content="{{ meta.image }}" />
|
||||||
<meta name="twitter:description" content="{{ meta.description }}" />
|
<meta name="twitter:description" content="{{ meta.description }}" />
|
||||||
<script type="module" crossorigin src="/assets/lms/frontend/assets/index-Ddsp6_Rz.js"></script>
|
<script type="module" crossorigin src="/assets/lms/frontend/assets/index-mfcOnHa1.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/lms/frontend/assets/frappe-ui-BI4McHL7.js">
|
<link rel="modulepreload" crossorigin href="/assets/lms/frontend/assets/frappe-ui-CgFK8870.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/lms/frontend/assets/frappe-ui-DzKBfka9.css">
|
<link rel="stylesheet" crossorigin href="/assets/lms/frontend/assets/frappe-ui-DzKBfka9.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/lms/frontend/assets/index-B8lu6r6G.css">
|
<link rel="stylesheet" crossorigin href="/assets/lms/frontend/assets/index-9UBJh53K.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
|||||||
@@ -22,5 +22,9 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/frappe/lms/issues"
|
"url": "https://github.com/frappe/lms/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/frappe/lms#readme"
|
"homepage": "https://github.com/frappe/lms#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"cypress": "^13.9.0",
|
||||||
|
"cypress-file-upload": "^5.0.8"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BIN
temp/IM029.jpg
Normal file
BIN
temp/IM029.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
BIN
temp/cashondelivery.png
Normal file
BIN
temp/cashondelivery.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
Reference in New Issue
Block a user