Browse Source

Merge pull request #3981 from nocodb/test/survey-mode

test: survey form
pull/3994/head
Raju Udava 2 years ago committed by GitHub
parent
commit
b4994c8ea7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 38
      packages/nc-gui/pages/[projectType]/form/[viewId]/index/survey.vue
  2. 191
      scripts/cypress/integration/common/4i_survey_form.js
  3. 2
      scripts/cypress/integration/test/pg-restViews.js
  4. 2
      scripts/cypress/integration/test/restViews.js
  5. 2
      scripts/cypress/integration/test/xcdb-restViews.js
  6. 3
      scripts/cypress/support/commands.js
  7. 5
      scripts/cypress/support/page_objects/mainPage.js

38
packages/nc-gui/pages/[projectType]/form/[viewId]/index/survey.vue

@ -158,11 +158,12 @@ onMounted(() => {
class="max-w-[max(33%,600px)] mx-auto flex flex-col justify-end" class="max-w-[max(33%,600px)] mx-auto flex flex-col justify-end"
> >
<div class="px-4 md:px-0 flex flex-col justify-end"> <div class="px-4 md:px-0 flex flex-col justify-end">
<h1 class="prose-2xl font-bold self-center my-4">{{ sharedFormView.heading }}</h1> <h1 class="prose-2xl font-bold self-center my-4" data-cy="nc-survey-form__heading">{{ sharedFormView.heading }}</h1>
<h2 <h2
v-if="sharedFormView.subheading && sharedFormView.subheading !== ''" v-if="sharedFormView.subheading && sharedFormView.subheading !== ''"
class="prose-lg text-slate-500 dark:text-slate-300 self-center mb-4 leading-6" class="prose-lg text-slate-500 dark:text-slate-300 self-center mb-4 leading-6"
data-cy="nc-survey-form__sub-heading"
> >
{{ sharedFormView?.subheading }} {{ sharedFormView?.subheading }}
</h2> </h2>
@ -197,7 +198,7 @@ onMounted(() => {
<LazySmartsheetVirtualCell <LazySmartsheetVirtualCell
v-if="isVirtualCol(field)" v-if="isVirtualCol(field)"
class="mt-0 nc-input" class="mt-0 nc-input"
:class="`nc-form-input-${field.title.replaceAll(' ', '')}`" :data-cy="`nc-survey-form__input-${field.title.replaceAll(' ', '')}`"
:column="field" :column="field"
/> />
@ -205,7 +206,7 @@ onMounted(() => {
v-else v-else
v-model="formState[field.title]" v-model="formState[field.title]"
class="nc-input" class="nc-input"
:class="`nc-form-input-${field.title.replaceAll(' ', '')}`" :data-cy="`nc-survey-form__input-${field.title.replaceAll(' ', '')}`"
:column="field" :column="field"
:edit-enabled="true" :edit-enabled="true"
/> />
@ -215,7 +216,7 @@ onMounted(() => {
{{ error.$message }} {{ error.$message }}
</div> </div>
<div class="block text-[14px]"> <div class="block text-[14px]" data-cy="nc-survey-form__field-description">
{{ field.description }} {{ field.description }}
</div> </div>
</div> </div>
@ -225,7 +226,12 @@ onMounted(() => {
<div class="ml-1 mt-4 flex w-full text-lg"> <div class="ml-1 mt-4 flex w-full text-lg">
<div class="flex-1 flex justify-center"> <div class="flex-1 flex justify-center">
<div v-if="isLast && !submitted && !v$.$invalid" class="text-center my-4"> <div v-if="isLast && !submitted && !v$.$invalid" class="text-center my-4">
<button type="submit" class="uppercase scaling-btn prose-sm" @click="submitForm"> <button
type="submit"
class="uppercase scaling-btn prose-sm"
data-cy="nc-survey-form__btn-submit"
@click="submitForm"
>
{{ $t('general.submit') }} {{ $t('general.submit') }}
</button> </button>
</div> </div>
@ -238,6 +244,7 @@ onMounted(() => {
> >
<button <button
class="bg-opacity-100 scaling-btn flex items-center gap-1" class="bg-opacity-100 scaling-btn flex items-center gap-1"
data-cy="nc-survey-form__btn-next"
:class="v$.localState[field.title]?.$error ? 'after:!bg-gray-100 after:!ring-red-500' : ''" :class="v$.localState[field.title]?.$error ? 'after:!bg-gray-100 after:!ring-red-500' : ''"
@click="goNext" @click="goNext"
> >
@ -262,7 +269,7 @@ onMounted(() => {
<Transition name="slide-left"> <Transition name="slide-left">
<div v-if="submitted" class="flex flex-col justify-center items-center text-center"> <div v-if="submitted" class="flex flex-col justify-center items-center text-center">
<div class="text-lg px-6 py-3 bg-green-300 text-gray-700 rounded"> <div class="text-lg px-6 py-3 bg-green-300 text-gray-700 rounded" data-cy="nc-survey-form__success-msg">
<template v-if="sharedFormView?.success_msg"> <template v-if="sharedFormView?.success_msg">
{{ sharedFormView?.success_msg }} {{ sharedFormView?.success_msg }}
</template> </template>
@ -282,7 +289,14 @@ onMounted(() => {
</p> </p>
<div v-if="sharedFormView?.submit_another_form" class="text-center"> <div v-if="sharedFormView?.submit_another_form" class="text-center">
<button type="button" class="scaling-btn bg-opacity-100" @click="resetForm">Submit Another Form</button> <button
type="button"
class="scaling-btn bg-opacity-100"
data-cy="nc-survey-form__btn-submit-another-form"
@click="resetForm"
>
Submit Another Form
</button>
</div> </div>
</div> </div>
</div> </div>
@ -292,7 +306,7 @@ onMounted(() => {
</div> </div>
<template v-if="!submitted"> <template v-if="!submitted">
<div class="mb-24 md:my-4 select-none text-center text-gray-500 dark:text-slate-200"> <div class="mb-24 md:my-4 select-none text-center text-gray-500 dark:text-slate-200" data-cy="nc-survey-form__footer">
{{ index + 1 }} / {{ formColumns?.length }} {{ index + 1 }} / {{ formColumns?.length }}
</div> </div>
</template> </template>
@ -304,7 +318,11 @@ onMounted(() => {
class="color-transition shadow-sm absolute bottom-18 right-1/2 transform translate-x-[50%] md:bottom-4 md:(right-12 transform-none) flex items-center bg-white border dark:bg-slate-500 rounded divide-x-1" class="color-transition shadow-sm absolute bottom-18 right-1/2 transform translate-x-[50%] md:bottom-4 md:(right-12 transform-none) flex items-center bg-white border dark:bg-slate-500 rounded divide-x-1"
> >
<a-tooltip :title="isFirst ? '' : 'Go to previous'" :mouse-enter-delay="0.25" :mouse-leave-delay="0"> <a-tooltip :title="isFirst ? '' : 'Go to previous'" :mouse-enter-delay="0.25" :mouse-leave-delay="0">
<button class="p-0.5 flex items-center group color-transition" @click="goPrevious"> <button
class="p-0.5 flex items-center group color-transition"
data-cy="nc-survey-form__icon-prev"
@click="goPrevious"
>
<MdiChevronLeft :class="isFirst ? 'text-gray-300' : 'group-hover:text-accent'" class="text-2xl md:text-md" /> <MdiChevronLeft :class="isFirst ? 'text-gray-300' : 'group-hover:text-accent'" class="text-2xl md:text-md" />
</button> </button>
</a-tooltip> </a-tooltip>
@ -314,7 +332,7 @@ onMounted(() => {
:mouse-enter-delay="0.25" :mouse-enter-delay="0.25"
:mouse-leave-delay="0" :mouse-leave-delay="0"
> >
<button class="p-0.5 flex items-center group color-transition" @click="goNext"> <button class="p-0.5 flex items-center group color-transition" data-cy="nc-survey-form__icon-next" @click="goNext">
<MdiChevronRight <MdiChevronRight
:class="isLast || v$.localState[field.title]?.$error ? 'text-gray-300' : 'group-hover:text-accent'" :class="isLast || v$.localState[field.title]?.$error ? 'text-gray-300' : 'group-hover:text-accent'"
class="text-2xl md:text-md" class="text-2xl md:text-md"

191
scripts/cypress/integration/common/4i_survey_form.js

@ -0,0 +1,191 @@
// test suite
//
import { isTestSuiteActive } from "../../support/page_objects/projectConstants";
import { mainPage } from "../../support/page_objects/mainPage";
import { loginPage } from "../../support/page_objects/navigation";
let linkText = "";
const generateShareLink_surveyMode = () => {
mainPage.shareView().click();
// ensure modal is rendered and visible
cy.getActiveModal(".nc-modal-share-view")
.find(".ant-modal-title")
.contains("This view is shared via a private link")
.should("be.visible");
// enable survey mode
cy.get('[data-cy="nc-modal-share-view__survey-mode"]').click();
// copy link text, save URL
cy.get('[data-cy="nc-modal-share-view__link"]').then(($el) => {
linkText = $el.text();
cy.log(linkText);
});
};
// Options:
// footer
// btnSubmit
// fieldLabel
//
function validateFormPage(options) {
// header & description
cy.get('[data-cy="nc-survey-form__heading"]')
.contains("A B C D")
.should("be.visible");
cy.get('[data-cy="nc-survey-form__sub-heading"]')
.contains("Survey form for testing")
.should("be.visible");
// footer (page index)
cy.get('[data-cy="nc-survey-form__footer"]')
.contains(options.footer)
.should("be.visible");
// submit button: will be either OK or Submit
cy.get(`[data-cy="nc-survey-form__${options.btnSubmit}"]`).should(
"be.visible"
);
// field label
cy.get(
`[data-cy="nc-survey-form__input-${options.fieldLabel.replaceAll(
" ",
""
)}"]`
).should("be.visible");
}
// test suite
//
export const genTest = (apiType, dbType) => {
if (!isTestSuiteActive(apiType, dbType)) return;
let clear;
/**
* class names specific to survey mode
* data-cy="nc-survey-form__heading"
* data-cy="nc-survey-form__sub-heading"
* data-cy="nc-survey-form__input-${fieldTitle}"
* data-cy="nc-survey-form__field-description"
* data-cy="nc-survey-form__btn-submit"
* data-cy="nc-survey-form__btn-next"
* data-cy="nc-survey-form__success-msg"
* data-cy="nc-survey-form__btn-submit-another-form"
* data-cy="nc-survey-form__footer"
* data-cy="nc-survey-form__icon-next"
* data-cy="nc-survey-form__icon-prev"
*/
describe(`${apiType.toUpperCase()} api - Kanban`, () => {
before(() => {
cy.restoreLocalStorage();
// disable CY storage handling
clear = Cypress.LocalStorage.clear;
Cypress.LocalStorage.clear = () => {};
});
after(() => {
// re-enable CY storage handling
Cypress.LocalStorage.clear = clear;
cy.saveLocalStorage();
});
it("Create form view", () => {
cy.openTableTab("Country", 25);
cy.viewCreate("form");
// prepare form
// wait for input fields to be rendered as enabled
cy.wait(2000);
// Update header & add some description
cy.get(".nc-form")
.find('[placeholder="Form Title"]')
.clear()
.type("A B C D");
cy.get(".nc-form")
.find('[placeholder="Add form description"]')
.type("Survey form for testing");
cy.get(".nc-form").click();
// add success message
cy.get("textarea.nc-form-after-submit-msg").type("Congratulations!");
// enable "Submit another form" check box
cy.get("button.nc-form-checkbox-submit-another-form").click();
// show another form after 5 seconds
cy.get("button.nc-form-checkbox-show-blank-form").click();
});
it("Share form, enable survey mode", () => {
generateShareLink_surveyMode();
cy.signOut();
});
it("Visit link, validate form", () => {
cy.visit(linkText);
// validate form
validateFormPage({
footer: "1 / 3",
btnSubmit: "btn-next",
fieldLabel: "Country",
});
cy.get('[data-cy="nc-survey-form__input-Country"]').type("x{enter}");
validateFormPage({
footer: "2 / 3",
btnSubmit: "btn-next",
fieldLabel: "LastUpdate",
});
cy.get('[data-cy="nc-survey-form__input-LastUpdate"]').click();
cy.get(".ant-picker-now-btn:visible").contains("Now").click();
cy.get(".ant-btn-primary:visible").contains("Ok").click();
cy.get('[data-cy="nc-survey-form__btn-next"]').click();
// takes time for the link field to be rendered
cy.wait(2000);
validateFormPage({
footer: "3 / 3",
btnSubmit: "btn-submit",
fieldLabel: "City List",
});
cy.get('[data-cy="nc-survey-form__btn-submit"]').click();
// validate success message
cy.get('[data-cy="nc-survey-form__success-msg"]')
.should("be.visible")
.contains("Congratulations!")
.should("be.visible");
// validate "Submit another form" button
cy.get('[data-cy="nc-survey-form__btn-submit-another-form"]').should(
"be.visible"
);
});
it("Delete form view", () => {
loginPage.loginAndOpenProject(apiType, dbType);
cy.openTableTab("Country", 25);
// clean up newly added rows into Country table operations
// this auto verifies successfull addition of rows to table as well
mainPage.getPagination(5).click();
// wait for page rendering to complete
cy.get(".nc-grid-row").should("have.length", 10);
mainPage.getCell("Country", 10).rightclick();
cy.getActiveMenu(".nc-dropdown-grid-context-menu")
.contains("Delete Row")
.click();
cy.viewDelete(0);
});
});
};

2
scripts/cypress/integration/test/pg-restViews.js

@ -8,6 +8,7 @@ let t4e = require("../common/4e_form_view_share");
let t4f = require("../common/4f_pg_grid_view_share"); let t4f = require("../common/4f_pg_grid_view_share");
let t4g = require("../common/4g_table_view_expanded_form"); let t4g = require("../common/4g_table_view_expanded_form");
let t4h = require("../common/4h_kanban"); let t4h = require("../common/4h_kanban");
let t4i = require("../common/4i_survey_form");
const { const {
setCurrentMode, setCurrentMode,
} = require("../../support/page_objects/projectConstants"); } = require("../../support/page_objects/projectConstants");
@ -25,6 +26,7 @@ const nocoTestSuite = (apiType, dbType) => {
t4f.genTest(apiType, dbType); t4f.genTest(apiType, dbType);
t4g.genTest(apiType, dbType); t4g.genTest(apiType, dbType);
t4h.genTest(apiType, dbType); t4h.genTest(apiType, dbType);
t4i.genTest(apiType, dbType);
}; };
nocoTestSuite("rest", "postgres"); nocoTestSuite("rest", "postgres");

2
scripts/cypress/integration/test/restViews.js

@ -8,6 +8,7 @@ let t4e = require("../common/4e_form_view_share");
let t4f = require("../common/4f_grid_view_share"); let t4f = require("../common/4f_grid_view_share");
let t4g = require("../common/4g_table_view_expanded_form"); let t4g = require("../common/4g_table_view_expanded_form");
let t4h = require("../common/4h_kanban"); let t4h = require("../common/4h_kanban");
let t4i = require("../common/4i_survey_form");
const { const {
setCurrentMode, setCurrentMode,
} = require("../../support/page_objects/projectConstants"); } = require("../../support/page_objects/projectConstants");
@ -25,6 +26,7 @@ const nocoTestSuite = (apiType, dbType) => {
t4f.genTest(apiType, dbType); t4f.genTest(apiType, dbType);
t4g.genTest(apiType, dbType); t4g.genTest(apiType, dbType);
t4h.genTest(apiType, dbType); t4h.genTest(apiType, dbType);
t4i.genTest(apiType, dbType);
}; };
nocoTestSuite("rest", "mysql"); nocoTestSuite("rest", "mysql");

2
scripts/cypress/integration/test/xcdb-restViews.js

@ -7,6 +7,7 @@ let t4d = require("../common/4d_table_view_grid_locked");
let t4e = require("../common/4e_form_view_share"); let t4e = require("../common/4e_form_view_share");
let t4f = require("../common/4f_grid_view_share"); let t4f = require("../common/4f_grid_view_share");
let t4h = require("../common/4h_kanban"); let t4h = require("../common/4h_kanban");
let t4i = require("../common/4i_survey_form");
const { const {
setCurrentMode, setCurrentMode,
} = require("../../support/page_objects/projectConstants"); } = require("../../support/page_objects/projectConstants");
@ -23,6 +24,7 @@ const nocoTestSuite = (apiType, dbType) => {
// to be fixed t4e.genTest(apiType, dbType); // to be fixed t4e.genTest(apiType, dbType);
t4f.genTest(apiType, dbType); t4f.genTest(apiType, dbType);
t4h.genTest(apiType, dbType); t4h.genTest(apiType, dbType);
t4i.genTest(apiType, dbType);
}; };
nocoTestSuite("rest", "xcdb"); nocoTestSuite("rest", "xcdb");

3
scripts/cypress/support/commands.js

@ -315,7 +315,7 @@ Cypress.Commands.add("getActiveDrawer", (selector) => {
Cypress.Commands.add("getActivePicker", (dropdownSelector) => { Cypress.Commands.add("getActivePicker", (dropdownSelector) => {
if (dropdownSelector) { if (dropdownSelector) {
return cy.get(`${dropdownSelector}.ant-drawer-content:visible`).last(); return cy.get(`${dropdownSelector}.ant-picker-dropdown:visible`).last();
} }
return cy.get(".ant-picker-dropdown :visible").last(); return cy.get(".ant-picker-dropdown :visible").last();
}); });
@ -535,6 +535,7 @@ function capitalizeFirstLetter(string) {
// viewCreate // viewCreate
// : viewType: grid, gallery, kanban, form // : viewType: grid, gallery, kanban, form
// : creates view with default name // : creates view with default name
// : [fix-me] with name validation, works only first view creation of that category.
// //
Cypress.Commands.add("viewCreate", (viewType) => { Cypress.Commands.add("viewCreate", (viewType) => {
// click on 'Grid/Gallery/Form/Kanban' button on Views bar // click on 'Grid/Gallery/Form/Kanban' button on Views bar

5
scripts/cypress/support/page_objects/mainPage.js

@ -47,7 +47,10 @@ export class _settingsPage {
} }
closeMenu() { closeMenu() {
cy.getActiveModal().find(".nc-modal-close").click({ force: true }); cy.getActiveModal()
.find(".nc-modal-close")
.scrollIntoView()
.click({ force: true });
} }
openProjectMenu() { openProjectMenu() {

Loading…
Cancel
Save