From 4404232d4d1231429a13da31aba534c382aebf82 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 10 Feb 2022 13:15:11 +0800 Subject: [PATCH 01/58] fix: allow different boolean values for checkbox type Signed-off-by: Wing-Kam Wong --- .../importExport/columnMappingModal.vue | 22 ++++++++++++++++++- .../spreadsheet/components/moreActions.vue | 15 +++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/components/project/spreadsheet/components/importExport/columnMappingModal.vue b/packages/nc-gui/components/project/spreadsheet/components/importExport/columnMappingModal.vue index 740342d0f5..c86b7afa86 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/importExport/columnMappingModal.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/importExport/columnMappingModal.vue @@ -158,8 +158,28 @@ export default { return 'Source data contains some invalid numbers' } break + case UITypes.Checkbox: + if ( + this.parsedCsv && this.parsedCsv.data && this.parsedCsv.data.slice(0, 500) + .some((r) => { + if (r => r[row.sourceCn] !== null && r[row.sourceCn] !== undefined) { + var input = r[row.sourceCn] + if (typeof input === 'string') { + input = input.replace(/["']/g, "").toLowerCase().trim() + return ( + input == "false" || input == "no" || input == "n" || input == "0" || + input == "true" || input == "yes" || input == "y" || input == "1" + ) ? false : true + } + return input != 1 && input != 0 && input != true && input != false + } + return false + }) + ) { + return 'Source data contains some invalid boolean values' + } + break } - return true }, mapDefaultColumns() { diff --git a/packages/nc-gui/components/project/spreadsheet/components/moreActions.vue b/packages/nc-gui/components/project/spreadsheet/components/moreActions.vue index d7dd20868f..756c041e29 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/moreActions.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/moreActions.vue @@ -106,6 +106,7 @@ import FileSaver from 'file-saver' import DropOrSelectFileModal from '~/components/import/dropOrSelectFileModal' import ColumnMappingModal from '~/components/project/spreadsheet/components/importExport/columnMappingModal' import CSVTemplateAdapter from '~/components/import/templateParsers/CSVTemplateAdapter' +import { UITypes } from '~/components/project/spreadsheet/helpers/uiTypes' export default { name: 'ExportImport', @@ -276,9 +277,19 @@ export default { for (let i = 0, progress = 0; i < data.length; i += 500) { const batchData = data.slice(i, i + 500).map(row => columnMappings.reduce((res, col) => { // todo: parse data - if (col.enabled && col.destCn) { - res[col.destCn] = row[col.sourceCn] + const v = this.meta && this.meta.columns.find(c => c._cn === col.destCn) + var input = row[col.sourceCn] + // parse potential boolean values + if (v.uidt == UITypes.Checkbox) { + input = input.replace(/["']/g, "").toLowerCase().trim() + if (input == "false" || input == "no" || input == "n") { + input = "0" + } else if (input == "true" || input == "yes" || input == "y") { + input = "1" + } + } + res[col.destCn] = input } return res }, {})) From b931a17d26c2bf6955ad3e48cd8c5a62c1519f0e Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 10 Feb 2022 13:40:29 +0800 Subject: [PATCH 02/58] fix: typo - change mets to meta Signed-off-by: Wing-Kam Wong --- packages/nocodb/src/lib/noco/NcProjectBuilder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nocodb/src/lib/noco/NcProjectBuilder.ts b/packages/nocodb/src/lib/noco/NcProjectBuilder.ts index ac7fb7db64..b3c488b1f7 100644 --- a/packages/nocodb/src/lib/noco/NcProjectBuilder.ts +++ b/packages/nocodb/src/lib/noco/NcProjectBuilder.ts @@ -696,7 +696,7 @@ export default class NcProjectBuilder { for (const connectionConfig of dbs) { try { const sqlClient = NcConnectionMgr.getSqlClient({ - dbAlias: connectionConfig?.mets?.dbAlias, + dbAlias: connectionConfig?.meta?.dbAlias, env: this.config.env, config: this.config, projectId: this.id @@ -892,7 +892,7 @@ export default class NcProjectBuilder { for (const connectionConfig of dbs) { NcConnectionMgr.delete({ - dbAlias: connectionConfig?.mets?.dbAlias, + dbAlias: connectionConfig?.meta?.dbAlias, env: this.config.env, projectId: this.id }); From 3c45e0c08de4db6f28ddfa1f2b26c3b748d62f7c Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 10 Feb 2022 15:48:22 +0530 Subject: [PATCH 03/58] [i18n] translation issue template, base version --- .github/ISSUE_TEMPLATE/I18n_translations.md | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/I18n_translations.md diff --git a/.github/ISSUE_TEMPLATE/I18n_translations.md b/.github/ISSUE_TEMPLATE/I18n_translations.md new file mode 100644 index 0000000000..b8e2e6fc26 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/I18n_translations.md @@ -0,0 +1,23 @@ +# i18n translation request + +**Please enter the following details** + +1. Select applicalbe +- [ ] **New language support request** +- [ ] **Existing language translation corrections request** +Verify if language support already exists in NocoDB i18n master spreadsheet [here](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) + +2. Associated language code (pick from [here](https://developers.google.com/admin-sdk/directory/v1/languages)): + +3. Google spreadsheet +- Procedure to share google spread sheet can be found [here](https://support.google.com/docs/answer/2494822?hl=en&co=GENIE.Platform%3DDesktop#zippy=%2Cshare-a-file-publicly) + - When requested, select public sharable link. +- Alternatively, you can download & attach spreadsheet here along with the issue as well. +- [ ] **Attached** +- [ ] **Shared link**: + +4. Summary of the changes made +- You can highlight modified items in Spreadsheet attached/shared, to help us quickly identify change set + +5. Any specific message to be conveyed to moderators? +- Help us simplify process if you find something hard about it From ce2b463ee6f51abc3c60d906e17d8c407b3e8806 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 10 Feb 2022 15:57:03 +0530 Subject: [PATCH 04/58] [chore] update issue templates for language & localization --- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .../i18n-translation-request.md | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/i18n-translation-request.md diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 3ecd2ab26e..45ca2e2ddc 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Feature request about: Suggest an idea for this project title: "[Feature] " -labels: Feature +labels: '' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/i18n-translation-request.md b/.github/ISSUE_TEMPLATE/i18n-translation-request.md new file mode 100644 index 0000000000..388183100d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/i18n-translation-request.md @@ -0,0 +1,32 @@ +--- +name: i18n translation request +about: translation & localisation support +title: "[i18n] Language support extension- " +labels: i18n translation +assignees: dstala + +--- + +# i18n translation request + +**Please enter the following details** + +1. Select applicalbe +- [ ] **New language support request** +- [ ] **Existing language translation corrections request** +Verify if language support already exists in the NocoDB i18n master spreadsheet [here](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) + +2. Associated language code (pick from [here](https://developers.google.com/admin-sdk/directory/v1/languages)): + +3. Google spreadsheet +- Procedure to share google spreadsheet can be found [here](https://support.google.com/docs/answer/2494822?hl=en&co=GENIE.Platform%3DDesktop#zippy=%2Cshare-a-file-publicly) + - When requested, select public sharable link. +- Alternatively, you can download & attach a spreadsheet here along with the issue as well. +- [ ] **Attached** +- [ ] **Shared link**: + +4. Summary of the changes made +- You can highlight modified items in the Spreadsheet attached/shared, to help us quickly identify changeset + +5. Any specific message to be conveyed to moderators? +- Help us simplify the process if you find something hard about it From feda1477d33fee6a1facba0d855d498e3ac382f9 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 10 Feb 2022 16:20:01 +0530 Subject: [PATCH 05/58] chore: noco-docs update for language translation Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- .../content/en/engineering/translation.md | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 packages/noco-docs/content/en/engineering/translation.md diff --git a/packages/noco-docs/content/en/engineering/translation.md b/packages/noco-docs/content/en/engineering/translation.md new file mode 100644 index 0000000000..53fc1d0af1 --- /dev/null +++ b/packages/noco-docs/content/en/engineering/translation.md @@ -0,0 +1,68 @@ +--- +title: "Language support" +description: "i18n: support for local/regional languages" +position: 2000 +category: "Engineering" +menuTitle: "Localization: i18n" +--- + +NocoDB supports tool localization & relies on Google translation for first version. We understand, Google translation would not always provide correct transaltion for the context. We accept PR for subsequent corrections from Open source enthusiasts and contributors worldwide. Any such corrections over-ride Google translation & are recorded in Master i18n spreadsheet. + +> **Resource Links** +> [Master i18n spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) +> [Google language code](https://developers.google.com/admin-sdk/directory/v1/languages) + +## 1. Requesting support for a `new language` + +- Make a copy of [Google spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) + Screenshot 2022-02-10 at 1 47 06 PM + +- Find your language code [here](https://developers.google.com/admin-sdk/directory/v1/languages) +- Replace cell $AB$1 (rightmost, containing text `en`) with language code obtained above. +- Google will generate first version translation in column AB. Review. Make changes as you find appropriate for various items listed. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. +- Download spreadsheet as .csv (`File > Download > Comma-seperated values (.csv)`). + Screenshot 2022-02-10 at 1 45 05 PM + +- Create new [issue](https://github.com/nocodb/nocodb/issues/new?assignees=dstala&labels=i18n+translation&template=i18n-translation-request.md&title=%5Bi18n%5D+Language+support+extension-+%3Clanguage+code%3E) request with a link to your spreadsheet from Step-1 (for us to verify & update master spreadsheet). + +## 2. Making contributions to `existing language` translations + +- Make a copy of [Google spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) + Screenshot 2022-02-10 at 1 47 06 PM + +- Find your language code [here](https://developers.google.com/admin-sdk/directory/v1/languages) +- Go to the column containing your language code derived above. Make changes as you find appropriate for various items listed. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. +- Download spreadsheet as .csv (`File > Download > Comma-seperated values (.csv)`). + Screenshot 2022-02-10 at 1 45 05 PM + +- Create new [issue](https://github.com/nocodb/nocodb/issues/new?assignees=dstala&labels=i18n+translation&template=i18n-translation-request.md&title=%5Bi18n%5D+Language+support+extension-+%3Clanguage+code%3E) request with a link to your spreadsheet from Step-1 (for us to verify & update master spreadsheet). + +--- + +> **_This is exclusive to NocoDB team members/ moderators only_** + +## 3. Adding/ updating KEY.STRING + +- Open master [Spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) +- For the string/ text under consideration, look-up in existing sheet if it exists already +- [New string already exists] Consider re-using it; align string key if required +- [New string need to be inserted] Insert a new record into appropriate categories as defined below +- Download spreadsheet as .csv (File > Download > Comma-seperated values (.csv, current sheet) +- Use noco-i18n-from-cli to generate new language JSON file +- Copy respective i18n/\*.json files to `nocodb/packages/nc-gui/lang` + +## 4. String KEY Categories + +- **General**: simple & common tokens (save, cancel, submit, open, close, home, and such) +- **Objects**: objects from NocoDB POV (project, table, field, column, view, page, and such) +- **Title**: screen headers (compact) (menu headers, modal headers) +- **Lables**: text box/ radio/ field headers (few words) (Labels over textbox, radio buttons, and such) +- **Activity**/ actions: work items (few words) (Create Project, Delete Table, Add Row, and such) +- **Tooltip**: additional information associated with work items (usually lengthy) (Additional information provided for activity) +- **Placeholder**: placeholders associated with various textboxes (Text placeholders) +- **Msg** + - Info: general/success category for everything + - Error: warnings & errors + - Toast: pop-up toast messages + +> Note: Mark String KEY name in `camelCase`. Use above list as priority order in case of ambiguity. From 3a0caf0f850fcfff024adab91e7c12d0daf1f503 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 10 Feb 2022 18:46:24 +0530 Subject: [PATCH 06/58] chore: [Language DE] i18n corrections. contributed by WeT-Klb Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- packages/nc-gui/lang/de.json | 378 +++++++++++++++++------------------ 1 file changed, 189 insertions(+), 189 deletions(-) diff --git a/packages/nc-gui/lang/de.json b/packages/nc-gui/lang/de.json index f2c99c11d8..113ccd40dc 100644 --- a/packages/nc-gui/lang/de.json +++ b/packages/nc-gui/lang/de.json @@ -1,10 +1,10 @@ { "general": { - "home": "Heim", - "load": "Belastung", - "open": "Offen", - "close": "Nah dran", - "yes": "ja", + "home": "Start", + "load": "Laden", + "open": "Öffnen", + "close": "Schließen", + "yes": "Ja", "no": "Nein", "ok": "OK", "and": "Und", @@ -14,7 +14,7 @@ "remove": "Entfernen", "save": "Speichern", "cancel": "Abbrechen", - "submit": "einreichen", + "submit": "Übermitteln", "create": "Erstellen", "delete": "Löschen", "update": "Aktualisieren", @@ -22,20 +22,20 @@ "reload": "Neu laden", "reset": "Zurücksetzen", "install": "Installieren", - "show": "Show", + "show": "Zeigen", "hide": "Verstecken", - "showAll": "Zeige alles", - "hideAll": "Versteck alles", - "showMore": "Zeig mehr", - "showOptions": "Optionen anzeigen.", - "hideOptions": "Optionen ausblenden.", - "showMenu": "Zeige das Menü", - "hideMenu": "Menü ausblenden.", - "addAll": "Füge alle Hinzu", + "showAll": "Alles zeigen", + "hideAll": "Alles verstecken", + "showMore": "Mehr anzeigen", + "showOptions": "Optionen anzeigen", + "hideOptions": "Optionen ausblenden", + "showMenu": "Menü anzeigen", + "hideMenu": "Menü ausblenden", + "addAll": "Alles hinzufügen", "removeAll": "Alles entfernen", - "signUp": "Anmeldung", - "signIn": "EINLOGGEN", - "signOut": "Austragen", + "signUp": "Anmelden", + "signIn": "Einloggen", + "signOut": "Ausloggen", "required": "Erforderlich", "preferred": "Bevorzugt", "mandatory": "Verpflichtend", @@ -45,24 +45,24 @@ "project": "Projekt", "projects": "Projekte", "table": "Tabelle", - "tables": "Tische", - "field": "Bereich", + "tables": "Tabellen", + "field": "Feld", "fields": "Felder", "column": "Spalte", - "columns": "Säulen", - "page": "Buchseite", + "columns": "Spalten", + "page": "Seite", "pages": "Seiten", "record": "Aufzeichnen", "records": "Aufzeichnungen", - "webhook": "WEBHOOK.", - "webhooks": "WebHooks", - "view": "Aussicht", + "webhook": "Webhook", + "webhooks": "Webhooks", + "view": "Ansicht", "views": "Ansichten", "viewType": { - "grid": "Grid", + "grid": "Gitter", "gallery": "Galerie", "form": "Formular", - "kanban": "Kanban.", + "kanban": "Kanban", "calendar": "Kalender" }, "user": "Nutzer", @@ -71,21 +71,21 @@ "roles": "Rollen", "roleType": { "owner": "Eigentümer", - "creator": "Schöpfer", - "editor": "Editor", + "creator": "Ersteller", + "editor": "Bearbeiter", "commenter": "Kommentator", "viewer": "Zuschauer" } }, "datatype": { - "ID": "ICH WÜRDE", + "ID": "ID", "ForeignKey": "Unbekannter Schlüssel", - "SingleLineText": "Einzelsteintext", + "SingleLineText": "Einzeiliger Text", "LongText": "Langer Text", "Attachment": "Anhang", "Checkbox": "Kontrollkästchen", "MultiSelect": "Mehrfachauswahl", - "SingleSelect": "Single Select.", + "SingleSelect": "Einfache Auswahl", "Collaborator": "Mitarbeiter", "Date": "Datum", "Year": "Jahr", @@ -98,15 +98,15 @@ "Currency": "Währung", "Percent": "Prozent", "Duration": "Dauer", - "Rating": "Nennen", + "Rating": "Klassifizierung", "Formula": "Formel", - "Rollup": "Aufrollen", + "Rollup": "Rollup", "Count": "Zählen", "Lookup": "Nachschlagen", - "DateTime": "Terminzeit", - "CreateTime": "Zeit schaffen", - "LastModifiedTime": "Letzte geänderte Zeit", - "AutoNumber": "Auto Nummer", + "DateTime": "Datum/Zeit", + "CreateTime": "Zeit erstellen", + "LastModifiedTime": "Zuletzt bearbeitet", + "AutoNumber": "Auto-Nummerierung", "Barcode": "Barcode", "Button": "Taste", "Password": "Passwort" @@ -115,78 +115,78 @@ "isEqual": "ist gleich", "isNotEqual": "ist nicht gleich", "isLike": "ist wie", - "isNot like": "Ist nicht wie", + "isNot like": "ist nicht wie", "isEmpty": "ist leer", "isNotEmpty": "ist nicht leer", "isNull": "ist Null", - "isNotNull": "ist nicht null" + "isNotNull": "ist nicht Null" }, "title": { "newProj": "Neues Projekt", "myProject": "Meine Projekte", - "formTitle": "Titel bilden", - "collabView": "Kollaborative Sicht", + "formTitle": "Formular Titel", + "collabView": "Mitarbeitersicht", "lockedView": "Gesperrter Blick", "personalView": "Persönliche Ansicht", "appStore": "Appstore", "team&auth": "Team & Auth.", "rolesUserMgmt": "Rollen & Benutzermanagement", - "userMgmt": "Benutzermanagement.", - "apiTokenMgmt": "API-Tokens-Management.", - "rolesMgmt": "Rollenmanagement.", + "userMgmt": "Benutzermanagement", + "apiTokenMgmt": "API-Tokens-Management", + "rolesMgmt": "Rollenmanagement", "projMeta": "Projektmetadaten", - "metaMgmt": "Meta-Management.", + "metaMgmt": "Meta-Management", "metadata": "Metadaten", "exportImportMeta": "Metadaten exportieren / importieren", - "metaOperations": "Metadatenoperationen.", - "audit": "Prüfung", + "metaOperations": "Metadatenoperationen", + "audit": "Audit", "auditLogs": "Audit-Log", "sqlMigrations": "SQL-Migrationen", "dbCredentials": "Datenbank-Anmeldeinformationen", "advancedParameters": "SSL & Erweiterte Parameter", - "headCreateProject": "Projekt erstellen | NocOdb", - "headLogin": "Anmelden | NocOdb", - "resetPassword": "Setzen Sie Ihr Passwort zurück" + "headCreateProject": "Projekt erstellen | NocoDB", + "headLogin": "Anmelden | NocoDB", + "resetPassword": "Passwort zurücksetzen" }, "labels": { "projName": "Projektname", - "viewName": "Name anzeigen.", - "viewLink": "Link anzeigen.", + "viewName": "Name anzeigen", + "viewLink": "Link anzeigen", "columnName": "Spaltenname", - "columnType": "Säulentyp", + "columnType": "Spaltentyp", "roleName": "Rollenname", "roleDescription": "Rollenbeschreibung", - "databaseType": "Geben Sie in der Datenbank ein", + "databaseType": "Typ in der Datenbank", "lengthValue": "Länge / Wert", - "dbType": "Datenbanktyp.", - "sqliteFile": "SQLite-Datei.", + "dbType": "Datenbanktyp", + "sqliteFile": "SQLite-Datei", "hostAddress": "Host-Adresse", "port": "Port-Nummer", - "username": "Nutzername", + "username": "Benutzername", "password": "Passwort", "action": "Aktion", "actions": "Aktionen", - "operation": "Betrieb", - "operationType": "Betriebstyp.", - "operationSubType": "Betriebsuntertyp", + "operation": "Vorgang", + "operationType": "Vorgangstyp", + "operationSubType": "Vorgangsuntertyp", "description": "Beschreibung", "authentication": "Authentifizierung", - "token": "Zeichen", + "token": "Token", "where": "Wo", "cache": "Zwischenspeicher", - "chat": "Plaudern", + "chat": "Chat", "email": "Email", - "storage": "Lager", + "storage": "Speicher", "uiAcl": "UI-ACL.", "models": "Modelle", - "syncState": "Sync-Zustand", + "syncState": "Sync-Stand", "created": "Erstellt", - "sqlOutput": "SQL-Ausgang", + "sqlOutput": "SQL-Ausgabe", "dbCreateIfNotExists": "Datenbank: Erstellen, falls nicht vorhanden", "clientKey": "Client-Schlüssel", - "clientCert": "Client Cert.", + "clientCert": "Client Cert", "serverCA": "Server CA", - "requriedCa": "CA Erforderlich", + "requriedCa": "Erforderliches CA", "requriedIdentity": "Erforderliche Identität", "inflection": { "tableName": "Flexion - Tabellenname", @@ -194,7 +194,7 @@ }, "community": { "starUs1": "Stern", - "starUs2": "uns auf Github.", + "starUs2": "uns auf Github", "bookDemo": "Buchen Sie eine kostenlose Demo", "getAnswered": "Erhalten Sie Antworten auf Ihre Fragen", "joinDiscord": "Discord beitreten", @@ -204,9 +204,9 @@ }, "activity": { "createProject": "Projekt erstellen", - "importProject": "Projektimport", + "importProject": "Projekt importieren", "searchProject": "Projekt suchen", - "editProject": "Projekt bearbeiten.", + "editProject": "Projekt bearbeiten", "stopProject": "Projekt stoppen", "startProject": "Projekt starten", "restartProject": "Projekt neu starten", @@ -214,21 +214,21 @@ "refreshProject": "Projekte aktualisieren", "saveProject": "Projekt speichern", "createProjectExtended": { - "extDB": "Erstellen mit einer
externen Datenbank", - "excel": "Projekt von Excel erstellen", - "template": "Projekt aus der Vorlage erstellen" + "extDB": "Erstellen durch Verbinden
mit einer externen Datenbank", + "excel": "Projekt aus Excel erstellen", + "template": "Projekt aus Vorlage erstellen" }, - "OkSaveProject": "OK & Save Project", + "OkSaveProject": "OK & Project speichern", "upgrade": { "available": "Upgrade verfügbar", "releaseNote": "Versionshinweise", - "howTo": "Wie aktualisiere ich?" + "howTo": "Wie wird aktualisiert?" }, - "translate": "Hilfe umsetzen", + "translate": "Übersetzen helfen", "account": { - "authToken": "Copy Auth-Token", - "swagger": "Swagger Apis Doc.", - "projInfo": "Projektinfo kopieren.", + "authToken": "Auth-Token kopieren", + "swagger": "Swagger Apis Doc", + "projInfo": "Projektinfo kopieren", "themes": "Themen" }, "sort": "Sortieren", @@ -237,70 +237,70 @@ "addFilter": "Filter hinzufügen", "share": "Teilen", "shareBase": { - "disable": "Freigegebene Basis deaktivieren.", + "disable": "Freigegebene Datenbank deaktivieren", "enable": "Jeder mit dem Link", - "link": "Gemeinsamer Basis-Link" + "link": "Freigegebene Datenbank-Link" }, "invite": "Einladen", "inviteMore": "Mehr einladen", "inviteTeam": "Team einladen", - "inviteToken": "Einladen", + "inviteToken": "Token einladen", "newUser": "Neuer Benutzer", "editUser": "Benutzer bearbeiten", "deleteUser": "Benutzer vom Projekt entfernen", - "resendInvite": "Senden Sie die E-Mail-Adresse ein", - "copyInviteURL": "Kopieren Laden Sie die URL ein", + "resendInvite": "Einladungs-Email erneut versenden", + "copyInviteURL": "Einladungs-URL kopieren", "newRole": "Neue Rolle", "reloadRoles": "Rollen neu laden", "nextPage": "Nächste Seite", "prevPage": "Vorherige Seite", - "nextRecord": "Nächster Rekord", - "previousRecord": "Bisherigen Rekord", + "nextRecord": "Nächster Eintrag", + "previousRecord": "Vorheriger Eintrag", "copyApiURL": "API-URL kopieren", "createTable": "Tabelle erstellen", - "refreshTable": "Tabellen erfrischt.", - "renameTable": "Tisch umbenennen", - "addField": "Fügen Sie diesem Tisch neues Feld hinzu", - "setPrimary": "Als Primärwert einstellen", - "addRow": "Neue Row hinzufügen", - "saveRow": "REIBEN REIBEN", + "refreshTable": "Tabellen aktualisieren", + "renameTable": "Tabelle umbenennen", + "addField": "Neues Feld zu dieser Tabelle hinzufügen", + "setPrimary": "Als Primärwert festlegen", + "addRow": "Neue Spalte hinzufügen", + "saveRow": "Spalte speichern", "insertRow": "Neue Reihe einfügen", "deleteRow": "Zeile löschen", "deleteSelectedRow": "Ausgewählte Zeilen löschen", - "importExcel": "Excel importieren", - "downloadCSV": "Download als CSV.", - "uploadCSV": "Laden Sie CSV hoch", + "importExcel": "Import Excel", + "downloadCSV": "Download als CSV", + "uploadCSV": "Hochladen CSV", "import": "Importieren", "importMetadata": "Metadaten importieren", "exportMetadata": "Metadaten exportieren", "clearMetadata": "Metadaten löschen", - "exportToFile": "Export in die Datei.", + "exportToFile": "Export in Datei", "changePwd": "Kennwort ändern", - "createView": "Eine Ansicht erstellen.", - "shareView": "Ansicht teilen.", - "listSharedView": "Gemeinsame Ansichtsliste", - "ListView": "Ansichten Liste.", + "createView": "Ansicht erstellen", + "shareView": "Ansicht teilen", + "listSharedView": "Geteilte Ansichtsliste", + "ListView": "Ansichtenliste", "copyView": "Ansicht kopieren", "renameView": "Ansicht umbenennen", "deleteView": "Ansicht löschen", - "createGrid": "Grid-Sicht erstellen.", - "createGallery": "Ansicht der Galerie erstellen.", - "createCalendar": "Kalender-Sicht erstellen.", - "createKanban": "Kanban-Sicht erstellen.", - "createForm": "Formula erstellen.", - "showSystemFields": "Systemfelder anzeigen.", + "createGrid": "Raster-Ansicht erstellen", + "createGallery": "Galerie-Ansicht erstellen", + "createCalendar": "Kalender-Ansicht erstellen", + "createKanban": "Kanban-Anicht erstellen", + "createForm": "Formular-Ansicht erstellen", + "showSystemFields": "Systemfelder anzeigen", "copyUrl": "URL kopieren", - "openTab": "Neue Registerkarte öffnen.", - "iFrame": "Kopieren Sie eingebettete HTML-Code", - "addWebhook": "Fügen Sie einen neuen WebHook hinzu", - "newToken": "Neues Token hinzufügen", + "openTab": "Neue Registerkarte öffnen", + "iFrame": "Eingebettete HTML-Code kopieren", + "addWebhook": "Neuen WebHook hinzufügen", + "newToken": "Neuen Token hinzufügen", "exportZip": "Zip-Datei exportieren", "importZip": "Zip-Datei importieren", "metaSync": "Jetzt synchronisieren", "settings": "Einstellungen", "previewAs": "Vorschau anzeigen als", - "resetReview": "Vorschau zurücksetzen.", - "testDbConn": "Datenbankverbindung testen.", + "resetReview": "Vorschau zurücksetzen", + "testDbConn": "Datenbankverbindung testen", "removeDbFromEnv": "Datenbank aus der Umgebung entfernen", "editConnJson": "Verbindung JSON bearbeiten", "sponsorUs": "Sponsor uns.", @@ -313,112 +313,112 @@ "apiGQL": "Zugänglich über Graphql-APIs", "theme": { "dark": "Es kommt in Schwarz (^ ⇧b)", - "light": "Kommt es schwarz? (^ ⇧b)" + "light": "Kommt es in schwarz? (^ ⇧b)" }, "addTable": "Neue Tabelle hinzufügen", - "inviteMore": "Laden Sie mehr Benutzer ein", - "toggleNavDraw": "Navigationsschublade umschalten", + "inviteMore": "Mehr Benutzer einladen", + "toggleNavDraw": "Navigationsbereich umschalten", "reloadApiToken": "API-Token neu laden", - "generateNewApiToken": "Neues API-Token generieren", + "generateNewApiToken": "Neuen API-Token generieren", "addRole": "Neue Rolle hinzufügen", - "metaReloadList": "Listenliste neu laden", - "metaSync": "Metadaten synchronisieren.", + "metaReloadList": "Liste neu laden", + "metaSync": "Metadaten synchronisieren", "sqlMigration": "Migrationen neu laden", - "updateRestart": "Update & Neustart.", - "cancelReturn": "Abbrechen und Rückkehr.", - "exportMetadata": "Exportieren Sie alle Metadaten von den Metastabellen in Meta-Verzeichnis.", - "importMetadata": "Importieren Sie alle Metadaten aus dem Meta-Verzeichnis in Meta-Tabellen.", + "updateRestart": "Update & Neustart", + "cancelReturn": "Abbrechen und Zurück", + "exportMetadata": "Alle Metadaten von den Metastabellen in Meta-Verzeichnis exportieren.", + "importMetadata": "Alle Metadaten vom Meta-Verzeichnis in Metastabellen importieren.", "clearMetadata": "Alle Metadaten aus Meta-Tabellen löschen.", - "clientKey": "Wählen Sie .key-Datei aus", - "clientCert": "Wählen Sie .Cert-Datei", - "clientCA": "Wählen Sie CA-Datei" + "clientKey": "Auswahl .key-Datei", + "clientCert": "Auswahl .cert-Datei", + "clientCA": "Auswahl CA-Datei" }, "placeholder": { - "projName": "Geben Sie den Projektnamen ein", + "projName": "Projektnamen eingeben", "password": { - "enter": "Geben Sie das Passwort ein", - "current": "Jetziges Passwort", + "enter": "Passwort eingeben", + "current": "Aktuelles Passwort", "new": "Neues Passwort", "save": "Passwort speichern", - "confirm": "Bestätige neues Passwort" + "confirm": "Neues Passwort bestätigen" }, - "searchProjectTree": "Tische suchen.", - "searchFields": "Suchfelder", - "searchColumn": "Suchen Sie {Suchen} Säule", + "searchProjectTree": "Tabellen suchen", + "searchFields": "Felder suchen", + "searchColumn": "Suche {search} Spalte", "searchApps": "Apps suchen", - "searchModels": "Suchmodelle", + "searchModels": "Suche Modelle", "noItemsFound": "Keine Elemente gefunden", "defaultValue": "Standardwert", - "filterByEmail": "Filtern per E-Mail" + "filterByEmail": "Filtern nach E-Mail" }, "msg": { "info": { - "footerInfo": "Reihen pro Seite.", - "upload": "Wählen Sie Datei zum Hochladen", - "upload_sub": "oder Drag & Drop-Datei", + "footerInfo": "Reihen pro Seite", + "upload": "Datei zum Hochladen auswählen", + "upload_sub": "oder Drag & Drop Datei", "excelSupport": "Unterstützt: .xls ,.xlsx ,.xlsm, .ods, .ots", - "excelURL": "Geben Sie Excel-Datei-URL ein", + "excelURL": "Excel-Datei-URL eingeben", "footMsg": "Anzahl der Zeilen, um den Datentyp analysieren zu können", "excelImport": "Blatt (s) stehen für den Import zur Verfügung", "exportMetadata": "Möchten Sie Metadaten von Meta-Tabellen exportieren?", - "importMetadata": "Möchten Sie Metadaten von Metastischen importieren?", - "clearMetadata": "Möchten Sie Metadaten von Meta-Tischen löschen?", - "projectEmptyMessage": "Beginnen Sie mit dem Erstellen eines neuen Projekts", - "stopProject": "Möchten Sie das Projekt aufhalten?", + "importMetadata": "Möchten Sie Metadaten von Metastabellen importieren?", + "clearMetadata": "Möchten Sie Metadaten von Meta-Tabellen löschen?", + "projectEmptyMessage": "Beginnen mit dem Erstellen eines neuen Projekts", + "stopProject": "Möchten Sie das Projekt beenden?", "startProject": "Möchten Sie das Projekt starten?", "restartProject": "Möchten Sie das Projekt neu starten?", "deleteProject": "Möchten Sie das Projekt löschen?", - "shareBasePrivate": "Öffentlich genutzbare readontly Base generieren", + "shareBasePrivate": "Öffentlich freigegebene Nur-Lese-Datenbank generieren", "shareBasePublic": "Jeder im Internet mit diesem Link kann sehen", - "userInviteNoSMTP": "Sieht aus, als hätten Sie den Mailer noch nicht konfiguriert! \\ n Bitte kopieren Sie den obigen Link einladen und senden Sie es an", - "dragDropHide": "Ziehen Sie die Felder hierher, um sich zu verstecken", - "formInput": "Geben Sie das Formular-Eingabetikett ein", - "formHelpText": "Fügen Sie etwas Hilfe Text hinzu", + "userInviteNoSMTP": "Sieht aus, als hätten Sie den Mailer noch nicht konfiguriert! \\ n Bitte kopieren Sie den obigen Einladungs-Link und senden Sie ihn an", + "dragDropHide": "Ziehen Sie die Felder hierher, um sie zu verstecken", + "formInput": "Formularbezeichnung eingeben", + "formHelpText": "Fügen Sie einen Hilfs-Text hinzu", "onlyCreator": "Nur für den Ersteller sichtbar", - "formDesc": "Formularbeschreibung hinzufügen.", + "formDesc": "Formularbeschreibung hinzufügen", "beforeEnablePwd": "Den Zugriff mit einem Passwort einschränken", - "afterEnablePwd": "Zugriff ist Passwort eingeschränkt", - "privateLink": "Diese Ansicht wird über einen privaten Link geteilt", - "privateLinkAdditionalInfo": "Personen mit privatem Link können nur Zellen sehen, die in dieser Ansicht angezeigt werden", - "afterFormSubmitted": "Nachdem das Formular eingereicht wird", - "apiOptions": "Zugriff auf Projekt via.", - "submitAnotherForm": "'Senden Sie ein anderes Formular einreichen'", - "showBlankForm": "Zeigen Sie nach 5 Sekunden ein leeres Formular an", - "emailForm": "E-Mail an mich an", - "showSysFields": "Systemfelder anzeigen.", - "filterAutoApply": "Automatisch anwenden.", - "showMessage": "Diese Nachricht anzeigen.", + "afterEnablePwd": "Zugriff ist Passwort-geschützt", + "privateLink": "Diese Ansicht wird durch einen privaten Link geteilt", + "privateLinkAdditionalInfo": "Personen mit einem privatem Link können nur Zellen sehen, die in dieser Ansicht angezeigt werden", + "afterFormSubmitted": "Nachdem das Formular übermittelt wurde", + "apiOptions": "Zugriff auf das Projekt via", + "submitAnotherForm": "Weiteres Formular übermitteln'-Button anzeigen", + "showBlankForm": "Ein leeres Formular nach 5 Sekunden anzeigen", + "emailForm": "E-Mail mich unter", + "showSysFields": "Systemfelder anzeigen", + "filterAutoApply": "Automatisch anwenden", + "showMessage": "Diese Nachricht anzeigen", "viewNotShared": "Aktuelle Ansicht wird nicht geteilt!", - "showAllViews": "Alle gemeinsamen Ansichten dieser Tabelle anzeigen", - "collabView": "Mitarbeitern mit Bearbeitungsberechtigungen oder höher können die Ansichtskonfiguration ändern.", - "lockedView": "Niemand kann die Ansichtskonfiguration bearbeiten, bis er freigeschaltet ist.", - "personalView": "Nur Sie können die Ansichtskonfiguration bearbeiten. Weitere persönliche Ansichten der Ankäufer sind standardmäßig ausgeblendet.", - "ownerDesc": "Können Ersteller hinzufügen / entfernen. Und Full-Edit-Datenbankstrukturen und -felder.", + "showAllViews": "Alle geteilten Ansichten dieser Tabelle anzeigen", + "collabView": "Mitarbeitern mit Bearbeitungsberechtigung oder höher können die Ansichtskonfiguration ändern", + "lockedView": "Niemand kann die Ansichtskonfiguration bearbeiten, bis sie freigeschaltet ist.", + "personalView": "Nur Sie können die Ansichtskonfiguration bearbeiten. Weitere Mitarbeiter-Ansichten sind standardmäßig ausgeblendet.", + "ownerDesc": "Kann Ersteller hinzufügen / entfernen und Datenbankstrukturen und -felder voll bearbeiten.", "creatorDesc": "Kann Datenbankstrukturen und Werte vollständig bearbeiten.", - "editorDesc": "Können Datensätze bearbeiten, aber die Struktur von Datenbanken / Feldern nicht ändern.", + "editorDesc": "Kann Datensätze bearbeiten, aber die Struktur von Datenbanken / Feldern nicht ändern.", "commenterDesc": "Kann die Datensätze anzeigen und kommentieren, aber nichts bearbeiten", - "viewerDesc": "Kann die Datensätze anzeigen, aber nichts bearbeiten", + "viewerDesc": "Kann die Einträge anzeigen, aber nichts bearbeiten", "addUser": "Neuen Benutzer hinzufügen", "staticRoleInfo": "Systemdefinierte Rollen können nicht bearbeitet werden", - "exportZip": "Exportieren Sie das Projekt Meta in ZIP-Datei und downloaden.", - "importZip": "Importieren Sie das Projekt Meta-ZIP-Datei und starten Sie erneut.", - "importText": "Importieren von NOCODB-Projekt, indem Sie Metadaten-ZIP-Datei hochladen", + "exportZip": "Projekt-Meta in ZIP-Datei exportieren und downloaden", + "importZip": "Projekt Meta-ZIP-Datei inportieren und neu starten.", + "importText": "Importieren von NOCODB-Projekt durch Hochladen von Metadaten-ZIP-Datei", "metaNoChange": "Keine Änderung identifiziert", - "sqlMigration": "Schema-Migrationen werden automatisch erstellt. Erstellen Sie eine Tabelle und aktualisieren Sie diese Seite.", - "dbConnectionStatus": "Umwelt validiert.", + "sqlMigration": "Schema-Migrationen werden automatisch erstellt. Tabelle erstellen und diese Seite aktualisieren.", + "dbConnectionStatus": "Umgebung validiert", "dbConnected": "Verbindung war erfolgreich", "notifications": { "no_new": "Keine neuen Benachrichtigungen", - "clear": "Löschen" + "clear": "Leeren" }, "sponsor": { "header": "Sie können uns helfen!", - "message": "Wir sind ein winziges Team, das Vollzeit, um die NOCODB-Open-Source zu erstellen. Wir glauben, dass ein Werkzeug wie NOCODB für jeden Problemlöser im Internet frei verfügbar sein sollte." + "message": "Wir sind ein winziges Team, das Vollzeit arbeitet, um die NOCODB-Open-Source zu machen. Wir glauben, dass ein Werkzeug wie NOCODB für jeden Problemlöser im Internet frei verfügbar sein sollte." }, - "loginMsg": "Melden Sie sich bei NOCODB an", + "loginMsg": "In NocoDB einloggen", "passwordRecovery": { "message_1": "Bitte geben Sie die E-Mail-Adresse an, die Sie bei der Anmeldung verwendet haben.", - "message_2": "Wir senden Ihnen eine E-Mail mit einem Link, um Ihr Passwort zurückzusetzen.", + "message_2": "Wir senden Ihnen eine E-Mail mit einem Link, um das Passwort zurückzusetzen.", "success": "Bitte überprüfen Sie Ihre E-Mail, um das Passwort zurückzusetzen" }, "signUp": { @@ -427,14 +427,14 @@ "workEmail": "Geben Sie Ihre Arbeits-E-Mail ein", "enterPassword": "Geben Sie Ihr Passwort ein", "forgotPassword": "Passwort vergessen ?", - "dontHaveAccount": "Ich habe kein Konto?" + "dontHaveAccount": "Sie haben kein Konto?" }, "addView": { - "grid": "Grid-Ansicht hinzufügen.", - "gallery": "Galerieansicht hinzufügen", - "form": "Fügen Sie den Formularansicht hinzu", - "kanban": "Kanban-Sicht hinzufügen", - "calendar": "Kalenderansicht hinzufügen" + "grid": "Gitter-Ansicht hinzufügen", + "gallery": "Galerie-Ansicht hinzufügen", + "form": "Formular-Ansicht hinzufügen", + "kanban": "Kanban-Ansicht hinzufügen", + "calendar": "Kalender-Ansicht hinzufügen" } }, "error": { @@ -447,9 +447,9 @@ "dbConnectionFailed": "Verbindungsfehler:", "signUpRules": { "emailReqd": "E-Mail ist erforderlich", - "emailInvalid": "Email muss gültig sein", + "emailInvalid": "Email muß gültig sein", "passwdRequired": "Passwort ist erforderlich", - "passwdLength": "Ihr Passwort muss mindestens 8 Zeichen sein" + "passwdLength": "Ihr Passwort muss mindestens 8 Zeichen haben" } }, "toast": { @@ -459,12 +459,12 @@ "stopProject": "Projekt wurde erfolgreich angehalten", "startProject": "Projekt begann erfolgreich", "restartProject": "Projekt neu gestartet", - "deleteProject": "Projekt erfolgreich gelöscht.", + "deleteProject": "Projekt erfolgreich gelöscht", "authToken": "Auth-Token in die Zwischenablage kopiert", - "projInfo": "Kopie Projektinformationen in die Zwischenablage", - "inviteUrlCopy": "Kopierte Laden Sie die URL in die Zwischenablage ein", - "createView": "Erfolgreich erstellt", - "formEmailSMTP": "Bitte aktivieren Sie das SMTP-Plugin in App Store, um die E-Mail-Benachrichtigung zu aktivieren", + "projInfo": "Projektinformationen in die Zwischenablage kopiert", + "inviteUrlCopy": "Einladungs-URL in die Zwischenablage kopiert", + "createView": "Ansicht erfolgreich erstelle", + "formEmailSMTP": "Bitte aktivieren Sie das SMTP-Plugin im App Store, um die E-Mail-Benachrichtigung zu aktivieren", "collabView": "Erfolgreich auf die kollaborative Ansicht gewechselt", "lockedView": "Erfolgreich auf gesperrte Ansicht gewechselt", "futureRelease": "Kommt bald!" From 8957a367ca2f390ac69ced3d1e1c31b340024af1 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 10 Feb 2022 19:07:47 +0530 Subject: [PATCH 07/58] chore: [Language DE] i18n corrections/2. contributed by WeT-Klb Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- packages/nc-gui/lang/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui/lang/de.json b/packages/nc-gui/lang/de.json index 113ccd40dc..53df690f7b 100644 --- a/packages/nc-gui/lang/de.json +++ b/packages/nc-gui/lang/de.json @@ -463,7 +463,7 @@ "authToken": "Auth-Token in die Zwischenablage kopiert", "projInfo": "Projektinformationen in die Zwischenablage kopiert", "inviteUrlCopy": "Einladungs-URL in die Zwischenablage kopiert", - "createView": "Ansicht erfolgreich erstelle", + "createView": "Ansicht erfolgreich erstellt", "formEmailSMTP": "Bitte aktivieren Sie das SMTP-Plugin im App Store, um die E-Mail-Benachrichtigung zu aktivieren", "collabView": "Erfolgreich auf die kollaborative Ansicht gewechselt", "lockedView": "Erfolgreich auf gesperrte Ansicht gewechselt", From 71c70b6968955a868cd8d6b97861e6d234ee3a90 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 10 Feb 2022 19:44:59 +0530 Subject: [PATCH 08/58] chore: noco-docs translation re-align Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- .../content/en/engineering/translation.md | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/noco-docs/content/en/engineering/translation.md b/packages/noco-docs/content/en/engineering/translation.md index 53fc1d0af1..9f39dffaac 100644 --- a/packages/noco-docs/content/en/engineering/translation.md +++ b/packages/noco-docs/content/en/engineering/translation.md @@ -12,26 +12,32 @@ NocoDB supports tool localization & relies on Google translation for first versi > [Master i18n spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) > [Google language code](https://developers.google.com/admin-sdk/directory/v1/languages) -## 1. Requesting support for a `new language` +## For Application User + +### 1. Changing `existing language` translation text + +Your help in identifying language translation anomalies & helping it fix helps in big way building/scaling NocoDB to next level. Please follow below simple procedure to request corrections to existing translation errors. - Make a copy of [Google spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) Screenshot 2022-02-10 at 1 47 06 PM - Find your language code [here](https://developers.google.com/admin-sdk/directory/v1/languages) -- Replace cell $AB$1 (rightmost, containing text `en`) with language code obtained above. -- Google will generate first version translation in column AB. Review. Make changes as you find appropriate for various items listed. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. +- Go to the column containing your language code derived above. Make changes as you find appropriate for various items listed. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. - Download spreadsheet as .csv (`File > Download > Comma-seperated values (.csv)`). Screenshot 2022-02-10 at 1 45 05 PM - Create new [issue](https://github.com/nocodb/nocodb/issues/new?assignees=dstala&labels=i18n+translation&template=i18n-translation-request.md&title=%5Bi18n%5D+Language+support+extension-+%3Clanguage+code%3E) request with a link to your spreadsheet from Step-1 (for us to verify & update master spreadsheet). -## 2. Making contributions to `existing language` translations +### 2. Requesting support for a `new language` + +Your native language not in list, we will be glad to support with your help! Please follow below steps - Make a copy of [Google spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) Screenshot 2022-02-10 at 1 47 06 PM - Find your language code [here](https://developers.google.com/admin-sdk/directory/v1/languages) -- Go to the column containing your language code derived above. Make changes as you find appropriate for various items listed. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. +- Replace cell $AB$1 (rightmost, containing text `en`) with language code obtained above. +- Google will generate first version translation in column AB. Review. Make changes as you find appropriate for various items listed. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. - Download spreadsheet as .csv (`File > Download > Comma-seperated values (.csv)`). Screenshot 2022-02-10 at 1 45 05 PM @@ -39,9 +45,11 @@ NocoDB supports tool localization & relies on Google translation for first versi --- +## For NocoDB Moderators + > **_This is exclusive to NocoDB team members/ moderators only_** -## 3. Adding/ updating KEY.STRING +### 1. Adding/ updating KEY.STRING - Open master [Spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) - For the string/ text under consideration, look-up in existing sheet if it exists already @@ -51,7 +59,7 @@ NocoDB supports tool localization & relies on Google translation for first versi - Use noco-i18n-from-cli to generate new language JSON file - Copy respective i18n/\*.json files to `nocodb/packages/nc-gui/lang` -## 4. String KEY Categories +### 2. String KEY Categories - **General**: simple & common tokens (save, cancel, submit, open, close, home, and such) - **Objects**: objects from NocoDB POV (project, table, field, column, view, page, and such) From 902a3afc76a4ef66a4bc0c7b3670db5c75f5bc66 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 10 Feb 2022 21:39:40 +0530 Subject: [PATCH 09/58] chore: i18n DE translation corrections/3, contributed by WeT-Klb Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- packages/nc-gui/lang/de.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/nc-gui/lang/de.json b/packages/nc-gui/lang/de.json index 53df690f7b..73978b2d12 100644 --- a/packages/nc-gui/lang/de.json +++ b/packages/nc-gui/lang/de.json @@ -106,7 +106,7 @@ "DateTime": "Datum/Zeit", "CreateTime": "Zeit erstellen", "LastModifiedTime": "Zuletzt bearbeitet", - "AutoNumber": "Auto-Nummerierung", + "AutoNumber": "Auto-Numerierung", "Barcode": "Barcode", "Button": "Taste", "Password": "Passwort" @@ -286,7 +286,7 @@ "createGrid": "Raster-Ansicht erstellen", "createGallery": "Galerie-Ansicht erstellen", "createCalendar": "Kalender-Ansicht erstellen", - "createKanban": "Kanban-Anicht erstellen", + "createKanban": "Kanban-Ansicht erstellen", "createForm": "Formular-Ansicht erstellen", "showSystemFields": "Systemfelder anzeigen", "copyUrl": "URL kopieren", @@ -326,8 +326,8 @@ "sqlMigration": "Migrationen neu laden", "updateRestart": "Update & Neustart", "cancelReturn": "Abbrechen und Zurück", - "exportMetadata": "Alle Metadaten von den Metastabellen in Meta-Verzeichnis exportieren.", - "importMetadata": "Alle Metadaten vom Meta-Verzeichnis in Metastabellen importieren.", + "exportMetadata": "Alle Metadaten von den Metatabellen in Meta-Verzeichnis exportieren.", + "importMetadata": "Alle Metadaten vom Meta-Verzeichnis in Metatabellen importieren.", "clearMetadata": "Alle Metadaten aus Meta-Tabellen löschen.", "clientKey": "Auswahl .key-Datei", "clientCert": "Auswahl .cert-Datei", @@ -361,7 +361,7 @@ "footMsg": "Anzahl der Zeilen, um den Datentyp analysieren zu können", "excelImport": "Blatt (s) stehen für den Import zur Verfügung", "exportMetadata": "Möchten Sie Metadaten von Meta-Tabellen exportieren?", - "importMetadata": "Möchten Sie Metadaten von Metastabellen importieren?", + "importMetadata": "Möchten Sie Metadaten von Metatabellen importieren?", "clearMetadata": "Möchten Sie Metadaten von Meta-Tabellen löschen?", "projectEmptyMessage": "Beginnen mit dem Erstellen eines neuen Projekts", "stopProject": "Möchten Sie das Projekt beenden?", @@ -401,7 +401,7 @@ "addUser": "Neuen Benutzer hinzufügen", "staticRoleInfo": "Systemdefinierte Rollen können nicht bearbeitet werden", "exportZip": "Projekt-Meta in ZIP-Datei exportieren und downloaden", - "importZip": "Projekt Meta-ZIP-Datei inportieren und neu starten.", + "importZip": "Projekt Meta-ZIP-Datei importieren und neu starten.", "importText": "Importieren von NOCODB-Projekt durch Hochladen von Metadaten-ZIP-Datei", "metaNoChange": "Keine Änderung identifiziert", "sqlMigration": "Schema-Migrationen werden automatisch erstellt. Tabelle erstellen und diese Seite aktualisieren.", @@ -413,7 +413,7 @@ }, "sponsor": { "header": "Sie können uns helfen!", - "message": "Wir sind ein winziges Team, das Vollzeit arbeitet, um die NOCODB-Open-Source zu machen. Wir glauben, dass ein Werkzeug wie NOCODB für jeden Problemlöser im Internet frei verfügbar sein sollte." + "message": "Wir sind ein winziges Team, das Vollzeit arbeitet, um die NOCODB-Open-Source zu machen. Wir glauben, daß ein Werkzeug wie NOCODB für jeden Problemlöser im Internet frei verfügbar sein sollte." }, "loginMsg": "In NocoDB einloggen", "passwordRecovery": { @@ -449,7 +449,7 @@ "emailReqd": "E-Mail ist erforderlich", "emailInvalid": "Email muß gültig sein", "passwdRequired": "Passwort ist erforderlich", - "passwdLength": "Ihr Passwort muss mindestens 8 Zeichen haben" + "passwdLength": "Ihr Passwort muß mindestens 8 Zeichen haben" } }, "toast": { From 3939ef448717996bb7b5c555a5f62bc1eca56d8b Mon Sep 17 00:00:00 2001 From: Naveen MR Date: Thu, 10 Feb 2022 17:03:13 +0000 Subject: [PATCH 10/58] refactor : docs Signed-off-by: Naveen MR --- .../content/en/engineering/translation.md | 76 ++++++++----------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/packages/noco-docs/content/en/engineering/translation.md b/packages/noco-docs/content/en/engineering/translation.md index 9f39dffaac..61ee642516 100644 --- a/packages/noco-docs/content/en/engineering/translation.md +++ b/packages/noco-docs/content/en/engineering/translation.md @@ -1,66 +1,54 @@ --- -title: "Language support" -description: "i18n: support for local/regional languages" +title: "i18n" +description: "Contribute to NocoDB's i18n translation" position: 2000 category: "Engineering" -menuTitle: "Localization: i18n" +menuTitle: "i18n" --- -NocoDB supports tool localization & relies on Google translation for first version. We understand, Google translation would not always provide correct transaltion for the context. We accept PR for subsequent corrections from Open source enthusiasts and contributors worldwide. Any such corrections over-ride Google translation & are recorded in Master i18n spreadsheet. +NocoDB supports many foreign languages & we welcome community contributions via an easy to use [google-spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172). +Your help in fixing i18n goes a long way supporting NocoDB. Please follow below simple procedure to request corrections to existing translation errors. -> **Resource Links** -> [Master i18n spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) -> [Google language code](https://developers.google.com/admin-sdk/directory/v1/languages) +## How to contribute ? (for community members) -## For Application User +### 1. How to change a string value ? +- Make a copy of [Google spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) + Screenshot 2022-02-10 at 1 47 06 PM +- Find your language code [here](https://developers.google.com/admin-sdk/directory/v1/languages) +- Go to the column containing your language code. Make necessary changes. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. +- Create a new [issue in Github] with a link to publicly accessible change details (https://github.com/nocodb/nocodb/issues/new?assignees=dstala&labels=i18n+translation&template=i18n-translation-request.md&title=%5Bi18n%5D+Language+support+extension-+%3Clanguage+code%3E) request with a link to your spreadsheet from Step-1 (for us to verify & update master spreadsheet). +- NocoDB Maintainers will take changes and merge it. -### 1. Changing `existing language` translation text -Your help in identifying language translation anomalies & helping it fix helps in big way building/scaling NocoDB to next level. Please follow below simple procedure to request corrections to existing translation errors. -- Make a copy of [Google spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) - Screenshot 2022-02-10 at 1 47 06 PM -- Find your language code [here](https://developers.google.com/admin-sdk/directory/v1/languages) -- Go to the column containing your language code derived above. Make changes as you find appropriate for various items listed. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. -- Download spreadsheet as .csv (`File > Download > Comma-seperated values (.csv)`). - Screenshot 2022-02-10 at 1 45 05 PM - -- Create new [issue](https://github.com/nocodb/nocodb/issues/new?assignees=dstala&labels=i18n+translation&template=i18n-translation-request.md&title=%5Bi18n%5D+Language+support+extension-+%3Clanguage+code%3E) request with a link to your spreadsheet from Step-1 (for us to verify & update master spreadsheet). - -### 2. Requesting support for a `new language` +### 2. How to add a new language ? Your native language not in list, we will be glad to support with your help! Please follow below steps -- Make a copy of [Google spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) - Screenshot 2022-02-10 at 1 47 06 PM - -- Find your language code [here](https://developers.google.com/admin-sdk/directory/v1/languages) -- Replace cell $AB$1 (rightmost, containing text `en`) with language code obtained above. -- Google will generate first version translation in column AB. Review. Make changes as you find appropriate for various items listed. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. -- Download spreadsheet as .csv (`File > Download > Comma-seperated values (.csv)`). - Screenshot 2022-02-10 at 1 45 05 PM - -- Create new [issue](https://github.com/nocodb/nocodb/issues/new?assignees=dstala&labels=i18n+translation&template=i18n-translation-request.md&title=%5Bi18n%5D+Language+support+extension-+%3Clanguage+code%3E) request with a link to your spreadsheet from Step-1 (for us to verify & update master spreadsheet). +- Make a copy of [Google spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) + Screenshot 2022-02-10 at 1 47 06 PM +- Find your language code [here](https://developers.google.com/admin-sdk/directory/v1/languages) +- Replace cell $AB$1 (rightmost, containing text `en`) with language code obtained above. +- Google will generate first version translation in column AB. Review. Make changes as you find appropriate for various items listed. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. +- Create new [issue](https://github.com/nocodb/nocodb/issues/new?assignees=dstala&labels=i18n+translation&template=i18n-translation-request.md&title=%5Bi18n%5D+Language+support+extension-+%3Clanguage+code%3E) request with a link to your spreadsheet from Step-1 (for us to verify & update master spreadsheet). --- -## For NocoDB Moderators - -> **_This is exclusive to NocoDB team members/ moderators only_** - -### 1. Adding/ updating KEY.STRING +## How to accept i18n contributions ? (for NocoDB maintainers) -- Open master [Spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) -- For the string/ text under consideration, look-up in existing sheet if it exists already -- [New string already exists] Consider re-using it; align string key if required -- [New string need to be inserted] Insert a new record into appropriate categories as defined below -- Download spreadsheet as .csv (File > Download > Comma-seperated values (.csv, current sheet) -- Use noco-i18n-from-cli to generate new language JSON file -- Copy respective i18n/\*.json files to `nocodb/packages/nc-gui/lang` +> _This is exclusive to NocoDB maintainers only_ -### 2. String KEY Categories +### 1. Adding / Updating a string +- Open master [Spreadsheet](https://docs.google.com/spreadsheets/d/1kGp92yLwhs1l7lwwgeor3oN1dFl7JZWuQOa4WSeZ0TE/edit#gid=2076107172) +- For the string/ text under consideration, look-up in existing sheet if it exists already +- [New string already exists] Consider re-using it; align string key if required +- [New string need to be inserted] Insert a new record into appropriate categories as defined below +- Download spreadsheet as .csv (File > Download > Comma-seperated values (.csv, current sheet) +- Use noco-i18n-from-cli to generate new language JSON file +- Copy respective i18n/\*.json files to `nocodb/packages/nc-gui/lang` +### 2. String Categories - **General**: simple & common tokens (save, cancel, submit, open, close, home, and such) - **Objects**: objects from NocoDB POV (project, table, field, column, view, page, and such) - **Title**: screen headers (compact) (menu headers, modal headers) @@ -73,4 +61,4 @@ Your native language not in list, we will be glad to support with your help! Ple - Error: warnings & errors - Toast: pop-up toast messages -> Note: Mark String KEY name in `camelCase`. Use above list as priority order in case of ambiguity. +> Note: string name should be in camelCase. Use above list as priority order in case of ambiguity. From 5c566b9f68d88fa190fbc8df9bd7ed02a7f4d3a7 Mon Sep 17 00:00:00 2001 From: Naveen MR Date: Thu, 10 Feb 2022 17:07:40 +0000 Subject: [PATCH 11/58] refactor : i18n docs Signed-off-by: Naveen MR --- packages/noco-docs/content/en/engineering/translation.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/noco-docs/content/en/engineering/translation.md b/packages/noco-docs/content/en/engineering/translation.md index 61ee642516..afaa686a11 100644 --- a/packages/noco-docs/content/en/engineering/translation.md +++ b/packages/noco-docs/content/en/engineering/translation.md @@ -16,8 +16,9 @@ Your help in fixing i18n goes a long way supporting NocoDB. Please follow below Screenshot 2022-02-10 at 1 47 06 PM - Find your language code [here](https://developers.google.com/admin-sdk/directory/v1/languages) - Go to the column containing your language code. Make necessary changes. Origin text in ENGLISH can be found in `Column B` of master spreadsheet. -- Create a new [issue in Github] with a link to publicly accessible change details (https://github.com/nocodb/nocodb/issues/new?assignees=dstala&labels=i18n+translation&template=i18n-translation-request.md&title=%5Bi18n%5D+Language+support+extension-+%3Clanguage+code%3E) request with a link to your spreadsheet from Step-1 (for us to verify & update master spreadsheet). +- Create a new [issue in Github](https://github.com/nocodb/nocodb/issues/new?assignees=dstala&labels=i18n+translation&template=i18n-translation-request.md&title=%5Bi18n%5D+Language+support+extension-+%3Clanguage+code%3E) request with a link to your spreadsheet from Step-1 (for us to verify & update master spreadsheet). - NocoDB Maintainers will take changes and merge it. +- It's that simple! From 6baef2e2fd3b87692bfd37f4de1517477803e8c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Feb 2022 02:17:29 +0000 Subject: [PATCH 12/58] chore(deps): Bump pathval in /packages/nc-migrator-archived Bumps [pathval](https://github.com/chaijs/pathval) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/chaijs/pathval/releases) - [Changelog](https://github.com/chaijs/pathval/blob/master/CHANGELOG.md) - [Commits](https://github.com/chaijs/pathval/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: pathval dependency-type: indirect ... Signed-off-by: dependabot[bot] --- packages/nc-migrator-archived/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nc-migrator-archived/package-lock.json b/packages/nc-migrator-archived/package-lock.json index ce196eaffc..f83ff7010b 100644 --- a/packages/nc-migrator-archived/package-lock.json +++ b/packages/nc-migrator-archived/package-lock.json @@ -4233,9 +4233,9 @@ } }, "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, "pg-connection-string": { From 07784069813979ecd7d898b9c0a21f041f332a0d Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 11 Feb 2022 12:29:36 +0800 Subject: [PATCH 13/58] fix: cast uuid in custom knex Signed-off-by: Wing-Kam Wong --- .../src/lib/dataMapper/lib/sql/CustomKnex.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts index ed9873ffc8..2bc54227dd 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts @@ -430,11 +430,19 @@ const appendWhereCondition = function( ); break; case '': - knexRef[`${key}`]( - columnAliases[matches[2]] || matches[2], - opMapping[matches[3]], - matches[4] - ); + const column = (columnAliases[matches[2]] || matches[2]); + const operator = opMapping[matches[3]]; + const target = matches[4]; + if (matches[3] == 'like') { + // handle uuid case + knexRef[`${key}`]( + knexRef?.client.raw(`??::TEXT ${operator} '${target}'`, [ + column + ]) + ); + } else { + knexRef[`${key}`](column, operator, target); + } break; default: throw new Error(`${matches[1] || ''} Invalid operation.`); @@ -991,6 +999,7 @@ export { Knex }; * * @author Naveen MR * @author Pranav C Balan + * @author Wing-Kam Wong * * @license GNU AGPL version 3 or any later version * From 1a28d2cd327856dbad7a35fa798f2423d97aab46 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 11 Feb 2022 12:30:13 +0800 Subject: [PATCH 14/58] fix: ESLint problems Signed-off-by: Wing-Kam Wong --- packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts index 2bc54227dd..68ec7b9775 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts @@ -430,7 +430,7 @@ const appendWhereCondition = function( ); break; case '': - const column = (columnAliases[matches[2]] || matches[2]); + const column = columnAliases[matches[2]] || matches[2]; const operator = opMapping[matches[3]]; const target = matches[4]; if (matches[3] == 'like') { From 60b793a6fbcd8c1243eed7d3e46ef53ca421d68e Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 11 Feb 2022 19:03:06 +0800 Subject: [PATCH 15/58] fix: add client type in custom knex Signed-off-by: Wing-Kam Wong --- packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts index 68ec7b9775..774833bb65 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts @@ -92,9 +92,10 @@ const appendWhereCondition = function( knexRef, isHaving = false ) { + const clientType = knexRef?.client?.config?.client; const opMapping = { ...opMappingGen, - ...(knexRef?.client?.config?.client === 'pg' ? { like: 'ilike' } : {}) + ...(clientType === 'pg' ? { like: 'ilike' } : {}) }; const camKey = isHaving ? 'Having' : 'Where'; const key = isHaving ? 'having' : 'where'; @@ -433,7 +434,7 @@ const appendWhereCondition = function( const column = columnAliases[matches[2]] || matches[2]; const operator = opMapping[matches[3]]; const target = matches[4]; - if (matches[3] == 'like') { + if (matches[3] == 'like' && clientType === 'pg') { // handle uuid case knexRef[`${key}`]( knexRef?.client.raw(`??::TEXT ${operator} '${target}'`, [ From 0efe569e7010a0b6b21e2830be072108ac7817a5 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 11 Feb 2022 19:03:37 +0800 Subject: [PATCH 16/58] fix: if it is bigint type, then go for eq instead of like Signed-off-by: Wing-Kam Wong --- .../components/project/spreadsheet/mixins/spreadsheet.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js b/packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js index 88b0fbbcd0..10c05784dc 100644 --- a/packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js +++ b/packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js @@ -163,7 +163,10 @@ export default { concatenatedXWhere() { let where = '' if (this.searchField && this.searchQuery.trim()) { - if (['text', 'string'].includes(this.sqlUi.getAbstractType(this.availableColumns.find(({ _cn }) => _cn === this.searchField) || this.availableColumns[0]))) { + const col = this.availableColumns.find(({ _cn }) => _cn === this.searchField) || this.availableColumns[0] + // bigint values are displayed in string format in UI + // when searching bigint values, the operator should be 'eq' instead of 'like' + if (['text', 'string'].includes(this.sqlUi.getAbstractType(col)) && col.dt !== 'bigint') { where = `(${this.searchField},like,%${this.searchQuery.trim()}%)` } else { where = `(${this.searchField},eq,${this.searchQuery.trim()})` From 8480271e356253d571f131b3537d0bfa768d5221 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 11 Feb 2022 19:05:13 +0800 Subject: [PATCH 17/58] fix: display bigint in string format Signed-off-by: Wing-Kam Wong --- packages/nc-gui/helpers/sqlUi/MssqlUi.js | 4 +--- packages/nc-gui/helpers/sqlUi/MysqlUi.js | 2 +- packages/nc-gui/helpers/sqlUi/SqliteUi.js | 2 +- packages/nocodb/src/lib/sqlUi/MssqlUi.ts | 4 +--- packages/nocodb/src/lib/sqlUi/MysqlUi.ts | 2 +- packages/nocodb/src/lib/sqlUi/SqliteUi.ts | 2 +- 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/nc-gui/helpers/sqlUi/MssqlUi.js b/packages/nc-gui/helpers/sqlUi/MssqlUi.js index 93a078fbcf..e44428a7fd 100644 --- a/packages/nc-gui/helpers/sqlUi/MssqlUi.js +++ b/packages/nc-gui/helpers/sqlUi/MssqlUi.js @@ -921,16 +921,14 @@ export class MssqlUi { static getAbstractType(col) { switch ((col.dt || col.dt).toLowerCase()) { - case 'bigint': case 'smallint': case 'bit': case 'tinyint': case 'int': return 'integer' + case 'bigint': case 'binary': - return 'string' - case 'char': return 'string' diff --git a/packages/nc-gui/helpers/sqlUi/MysqlUi.js b/packages/nc-gui/helpers/sqlUi/MysqlUi.js index 325b74967c..090cb51e14 100644 --- a/packages/nc-gui/helpers/sqlUi/MysqlUi.js +++ b/packages/nc-gui/helpers/sqlUi/MysqlUi.js @@ -842,7 +842,6 @@ export class MysqlUi { case 'int': case 'smallint': case 'mediumint': - case 'bigint': case 'bit': return 'integer' @@ -897,6 +896,7 @@ export class MysqlUi { case 'set': return 'set' + case 'bigint': case 'geometry': case 'point': case 'linestring': diff --git a/packages/nc-gui/helpers/sqlUi/SqliteUi.js b/packages/nc-gui/helpers/sqlUi/SqliteUi.js index 89c459ed79..21967e76c8 100644 --- a/packages/nc-gui/helpers/sqlUi/SqliteUi.js +++ b/packages/nc-gui/helpers/sqlUi/SqliteUi.js @@ -683,7 +683,6 @@ export class SqliteUi { case 'tinyint': case 'smallint': case 'mediumint': - case 'bigint': case 'int2': case 'int8': return 'integer' @@ -702,6 +701,7 @@ export class SqliteUi { case 'blob': return 'blob' + case 'bigint': case 'character': case 'varchar': return 'string' diff --git a/packages/nocodb/src/lib/sqlUi/MssqlUi.ts b/packages/nocodb/src/lib/sqlUi/MssqlUi.ts index 015b487504..193957d52f 100644 --- a/packages/nocodb/src/lib/sqlUi/MssqlUi.ts +++ b/packages/nocodb/src/lib/sqlUi/MssqlUi.ts @@ -937,16 +937,14 @@ export class MssqlUi { static getAbstractType(col): any { switch ((col.dt || col.dt).toLowerCase()) { - case 'bigint': case 'smallint': case 'bit': case 'tinyint': case 'int': return 'integer'; + case 'bigint': case 'binary': - return 'string'; - case 'char': return 'string'; diff --git a/packages/nocodb/src/lib/sqlUi/MysqlUi.ts b/packages/nocodb/src/lib/sqlUi/MysqlUi.ts index 44fb40372a..81b3f3d0d3 100644 --- a/packages/nocodb/src/lib/sqlUi/MysqlUi.ts +++ b/packages/nocodb/src/lib/sqlUi/MysqlUi.ts @@ -868,7 +868,6 @@ export class MysqlUi { case 'int': case 'smallint': case 'mediumint': - case 'bigint': case 'bit': return 'integer'; @@ -922,6 +921,7 @@ export class MysqlUi { case 'set': return 'set'; + case 'bigint': case 'geometry': case 'point': case 'linestring': diff --git a/packages/nocodb/src/lib/sqlUi/SqliteUi.ts b/packages/nocodb/src/lib/sqlUi/SqliteUi.ts index 2de293a440..37464e34e6 100644 --- a/packages/nocodb/src/lib/sqlUi/SqliteUi.ts +++ b/packages/nocodb/src/lib/sqlUi/SqliteUi.ts @@ -694,7 +694,6 @@ export class SqliteUi { case 'tinyint': case 'smallint': case 'mediumint': - case 'bigint': case 'int2': case 'int8': return 'integer'; @@ -713,6 +712,7 @@ export class SqliteUi { case 'blob': return 'blob'; + case 'bigint': case 'character': case 'varchar': return 'string'; From 003420303e2965bcf21a211a3a62e13555135684 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Feb 2022 14:52:42 +0000 Subject: [PATCH 18/58] chore(deps): Bump handlebars from 4.7.6 to 4.7.7 in /packages/nc-common Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.7.6 to 4.7.7. - [Release notes](https://github.com/wycats/handlebars.js/releases) - [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md) - [Commits](https://github.com/wycats/handlebars.js/compare/v4.7.6...v4.7.7) --- updated-dependencies: - dependency-name: handlebars dependency-type: indirect ... Signed-off-by: dependabot[bot] --- packages/nc-common/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nc-common/package-lock.json b/packages/nc-common/package-lock.json index fb0c9c1716..b3dd362845 100644 --- a/packages/nc-common/package-lock.json +++ b/packages/nc-common/package-lock.json @@ -5208,9 +5208,9 @@ "dev": true }, "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { "minimist": "^1.2.5", From bc8a3b8e4799b084557fa9d10198c2c6a27366c5 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 12 Feb 2022 11:58:28 +0800 Subject: [PATCH 19/58] fix: missing add row option when PK isn't available Signed-off-by: Wing-Kam Wong --- .../nc-gui/components/project/spreadsheet/views/xcGridView.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue b/packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue index fd5f9ce4e7..379d40f0d5 100644 --- a/packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue +++ b/packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue @@ -237,7 +237,7 @@ /> - + +
mdi-plus - New User + + {{ $t('activity.newUser') }}
@@ -313,7 +326,7 @@ - Share : {{ $store.getters['project/GtrProjectName'] }} + {{ $t('activity.share') }} : {{ $store.getters['project/GtrProjectName'] }} + {{ $t('activity.inviteTeam') }}
@@ -366,9 +380,10 @@

- Looks like you have not configured mailer yet!
Please copy above - invite - link and send it to + {{ $t('msg.info.userInviteNoSMTP') }} + + + {{ invite_token && (invite_token.email || invite_token.emails && invite_token.emails.join(', ')) }}.

@@ -407,7 +422,10 @@ @input="edited=true" > @@ -442,6 +460,8 @@ + +
{{ selectedUser.id ? 'save' : 'mdi-send' }} - {{ selectedUser.id ? 'Save' : 'Invite' }} + {{ selectedUser.id ? $t('general.save') : $t('activity.invite') }}
diff --git a/packages/nc-gui/components/base/shareBase.vue b/packages/nc-gui/components/base/shareBase.vue index 088ca49716..19466797cc 100644 --- a/packages/nc-gui/components/base/shareBase.vue +++ b/packages/nc-gui/components/base/shareBase.vue @@ -3,23 +3,46 @@ mdi-open-in-new - Shared base link + + + {{ $t('activity.shareBase.link') }} +
{{ url }} - + + + mdi-reload - + + + mdi-content-copy - + + + mdi-open-in-new - + + + mdi-xml
@@ -31,8 +54,14 @@ @@ -134,7 +136,8 @@ export default { 'created_at', 'updated_at'] }, - validateTableName + validateTableName, + valid: false } }, computed: { From 7eafd83d8ffe3deee545cb2e73b07224ad58960f Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 16 Feb 2022 19:27:38 +0800 Subject: [PATCH 48/58] fix: PR settings in release-npm.yml Signed-off-by: Wing-Kam Wong --- .github/workflows/release-npm.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index db4dd43011..d968a40a9d 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -48,19 +48,13 @@ jobs: # committer: GitHub # author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> signoff: true - branch: release-patches + branch: 'release/${{ github.event.inputs.tag || inputs.tag }}' delete-branch: true title: 'Release ${{ github.event.inputs.tag || inputs.tag }}' + reviewers: o1lab,pranavcx,dstala,wingkwong labels: | - automerge - + Bot: Automated PR - name: Check outputs run: | echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" - echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" - - - name: automerge - uses: "pascalgn/automerge-action@v0.14.3" - env: - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - PULL_REQUEST: "${{ steps.cpr.outputs.pull-request-number }}" \ No newline at end of file + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" \ No newline at end of file From 6b3bd4407a230007feb7147849c30af43e758b7c Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 16 Feb 2022 19:33:44 +0800 Subject: [PATCH 49/58] fix: add missing input for release-draft-note Signed-off-by: Wing-Kam Wong --- .github/workflows/release-nocodb.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release-nocodb.yml b/.github/workflows/release-nocodb.yml index 7d9a0f8561..cc6968ff54 100644 --- a/.github/workflows/release-nocodb.yml +++ b/.github/workflows/release-nocodb.yml @@ -32,6 +32,9 @@ jobs: release-draft-note: needs: close-issues users: ./.github/workflows/release-draft.yml + with: + tag: tag + prev_tag: prev_tag # Build docker image and push to docker hub release-docker: needs: release-draft-note From aba69dc78ec092f83587195c5f276fec1e86116e Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 16 Feb 2022 20:13:01 +0800 Subject: [PATCH 50/58] fix: add automerge Signed-off-by: Wing-Kam Wong --- .github/workflows/release-npm.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index d968a40a9d..6a9646791a 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -51,10 +51,14 @@ jobs: branch: 'release/${{ github.event.inputs.tag || inputs.tag }}' delete-branch: true title: 'Release ${{ github.event.inputs.tag || inputs.tag }}' - reviewers: o1lab,pranavcx,dstala,wingkwong labels: | Bot: Automated PR - name: Check outputs run: | echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" - echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" \ No newline at end of file + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" + - name: automerge + uses: "pascalgn/automerge-action@v0.14.3" + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + PULL_REQUEST: "${{ steps.cpr.outputs.pull-request-number }}" \ No newline at end of file From e2aa54701f648fc83dd59b37a8d9da08fdc56df5 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 16 Feb 2022 20:13:41 +0800 Subject: [PATCH 51/58] feat: add sync-to-develop Signed-off-by: Wing-Kam Wong --- .github/workflows/release-nocodb.yml | 22 +++++++++++++++------- .github/workflows/sync-to-develop.yml | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/sync-to-develop.yml diff --git a/.github/workflows/release-nocodb.yml b/.github/workflows/release-nocodb.yml index cc6968ff54..908b2dac30 100644 --- a/.github/workflows/release-nocodb.yml +++ b/.github/workflows/release-nocodb.yml @@ -11,11 +11,6 @@ on: description: "Previous Tag" required: true jobs: - # Build, install, publish frontend and backend to npm - release-npm: - uses: ./.github/workflows/release-npm.yml - with: - tag: tag # Close all issues with target tags 'Fixed' & 'Resolved' # TODO: add 'Fixed in vX.Y.Z' comment after closing. close-fixed-issues: @@ -28,16 +23,29 @@ jobs: uses: ./.github/workflows/release-close-issue.yml with: issue_label: 'Resolved' + + # Build, install, publish frontend and backend to npm + release-npm: + uses: ./.github/workflows/release-npm.yml + with: + tag: tag + # Draft Release Note release-draft-note: needs: close-issues - users: ./.github/workflows/release-draft.yml + uses: ./.github/workflows/release-draft.yml with: tag: tag prev_tag: prev_tag + # Build docker image and push to docker hub release-docker: needs: release-draft-note - users: ./.gitjib/workflows/release-docker.yml + uses: ./.github/workflows/release-docker.yml with: tag: tag + + # Sync changes to develop + sync-to-develop: + needs: release-docker + uses: ./.github/workflows/sync-to-develop.yml \ No newline at end of file diff --git a/.github/workflows/sync-to-develop.yml b/.github/workflows/sync-to-develop.yml new file mode 100644 index 0000000000..74fa9837ec --- /dev/null +++ b/.github/workflows/sync-to-develop.yml @@ -0,0 +1,20 @@ +name: 'Sync changes back to develop branch' + +on: + # Triggered manually + workflow_dispatch: + # Triggered by release-nocodb.yml + workflow_call: +jobs: + close-issues: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + + - name: Merge master -> develop + uses: devmasx/merge-branch@master + with: + type: now + from_branch: master + target_branch: develop + github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From eb879007b9ffc6a773800052c3fc26e43df239e6 Mon Sep 17 00:00:00 2001 From: Naveen MR Date: Wed, 16 Feb 2022 13:39:05 +0000 Subject: [PATCH 52/58] fix : Calendly link Signed-off-by: Naveen MR --- packages/nc-gui/layouts/default.vue | 2 +- packages/nc-gui/pages/projects/index.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/layouts/default.vue b/packages/nc-gui/layouts/default.vue index 8fbcb8d2f0..850588b98c 100644 --- a/packages/nc-gui/layouts/default.vue +++ b/packages/nc-gui/layouts/default.vue @@ -47,7 +47,7 @@ From e27960ee075ee550a40c8695c8d62228652ce16d Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Wed, 16 Feb 2022 20:11:04 +0530 Subject: [PATCH 54/58] fix: replace formula needs min 3 arg Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- packages/nc-gui/helpers/formulaList.js | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/nc-gui/helpers/formulaList.js b/packages/nc-gui/helpers/formulaList.js index 45553c2070..67a0207684 100644 --- a/packages/nc-gui/helpers/formulaList.js +++ b/packages/nc-gui/helpers/formulaList.js @@ -1,32 +1,32 @@ const validations = { AVG: { validation: { - args: { min: 1 } - } + args: { min: 1 }, + }, }, ADD: { validation: { - args: { min: 1 } - } + args: { min: 1 }, + }, }, AND: { validation: { - args: { min: 1 } - } + args: { min: 1 }, + }, }, OR: { validation: { - args: { min: 1 } - } + args: { min: 1 }, + }, }, CONCAT: { - validation: { args: { min: 1 } } + validation: { args: { min: 1 } }, }, TRIM: { - validation: { args: { min: 1 } } + validation: { args: { min: 1 } }, }, UPPER: { - validation: { args: { rqd: 1 } } + validation: { args: { rqd: 1 } }, }, LOWER: { validation: { args: { rqd: 1 } } }, LEN: { validation: { args: { rqd: 1 } } }, @@ -43,18 +43,18 @@ const validations = { SQRT: { validation: { args: { rqd: 1 } } }, ABS: { validation: { args: { rqd: 1 } } }, NOW: { validation: { args: { rqd: 0 } } }, - REPLACE: { validation: { args: { rqd: 2 } } }, + REPLACE: { validation: { args: { rqd: 3 } } }, SEARCH: { validation: { args: { rqd: 2 } } }, INT: { validation: { args: { rqd: 1 } } }, RIGHT: { validation: { args: { rqd: 2 } } }, LEFT: { - validation: { args: { rqd: 1 } } + validation: { args: { rqd: 1 } }, }, SUBSTR: { validation: { args: { min: 2, max: 3 } } }, MID: { validation: { args: { rqd: 1 } } }, IF: { validation: { args: { min: 2, max: 3 } } }, - SWITCH: { validation: { args: { min: 3 } } } -} + SWITCH: { validation: { args: { min: 3 } } }, +}; -export default Object.keys(validations) -export { validations } +export default Object.keys(validations); +export { validations }; From bb7f3e38c4e6bc64ebbc3513ecfe27978f8cf42b Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 17 Feb 2022 12:16:48 +0800 Subject: [PATCH 55/58] fix: variable syntax & pass version to release-close-issue Signed-off-by: Wing-Kam Wong --- .github/workflows/release-nocodb.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release-nocodb.yml b/.github/workflows/release-nocodb.yml index 908b2dac30..5f427fb0a5 100644 --- a/.github/workflows/release-nocodb.yml +++ b/.github/workflows/release-nocodb.yml @@ -12,38 +12,39 @@ on: required: true jobs: # Close all issues with target tags 'Fixed' & 'Resolved' - # TODO: add 'Fixed in vX.Y.Z' comment after closing. close-fixed-issues: needs: release-npm uses: ./.github/workflows/release-close-issue.yml with: issue_label: 'Fixed' + version: ${{ github.event.inputs.tag }} close-resolved-issues: needs: close-fixed-issues uses: ./.github/workflows/release-close-issue.yml with: issue_label: 'Resolved' + version: ${{ github.event.inputs.tag }} # Build, install, publish frontend and backend to npm release-npm: uses: ./.github/workflows/release-npm.yml with: - tag: tag + tag: ${{ github.event.inputs.tag }} # Draft Release Note release-draft-note: needs: close-issues uses: ./.github/workflows/release-draft.yml with: - tag: tag - prev_tag: prev_tag + tag: ${{ github.event.inputs.tag }} + prev_tag: ${{ github.event.inputs.prev_tag }} # Build docker image and push to docker hub release-docker: needs: release-draft-note uses: ./.github/workflows/release-docker.yml with: - tag: tag + tag: ${{ github.event.inputs.tag }} # Sync changes to develop sync-to-develop: From 45ecf11de5a9789753a9e38a4ac0d8ccc3ebfc9e Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 17 Feb 2022 12:17:09 +0800 Subject: [PATCH 56/58] feat: add version in release-close-issue Signed-off-by: Wing-Kam Wong --- .github/workflows/release-close-issue.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-close-issue.yml b/.github/workflows/release-close-issue.yml index bfa06021e6..b8e3c438a7 100644 --- a/.github/workflows/release-close-issue.yml +++ b/.github/workflows/release-close-issue.yml @@ -7,6 +7,9 @@ on: issue_label: description: "All issues with such label will be closed" required: true + version: + description: "Which version is this issue fixed in" + required: true # Triggered by release-nocodb.yml workflow_call: inputs: @@ -14,13 +17,18 @@ on: description: "All issues with such label will be closed" required: true type: string + version: + description: "Which version is this issue fixed in" + required: true + type: string jobs: close-issues: runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: close-resolved-issues - uses: bdougie/close-issues-based-on-label@master + uses: wingkwong/close-issues-based-on-label@master env: LABEL: ${{ github.event.inputs.issue_label || inputs.issue_label }} + VERSION: ${{ github.event.inputs.version || inputs.version }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 897c861986a8a65b1c8ca3dc904a437d18850888 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 17 Feb 2022 10:28:36 +0530 Subject: [PATCH 57/58] chore: cypress screenshots Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- .gitignore | 1 + scripts/cypress/cypress.json | 3 +- .../common/00_pre_configurations.js | 1 + .../integration/common/1a_table_operations.js | 2 + .../common/1b_table_column_operations.js | 323 +++---- .../1d_pg_table_view_drag_drop_reorder.js | 2 + .../common/1d_table_view_drag_drop_reorder.js | 2 + .../integration/common/1e_meta_sync.js | 319 +++---- .../2a_table_with_belongs_to_colulmn.js | 104 ++- .../common/2b_table_with_m2m_column.js | 151 ++-- .../3a_filter_sort_fields_operations.js | 419 ++++----- .../integration/common/3b_formula_column.js | 3 + .../integration/common/3c_lookup_column.js | 190 ++-- .../integration/common/3d_rollup_column.js | 2 + .../common/4a_table_view_grid_gallery_form.js | 137 +-- .../integration/common/4b_table_view_share.js | 5 + .../common/4d_table_view_grid_locked.js | 1 + .../integration/common/4e_form_view_share.js | 385 +++++---- .../integration/common/4f_grid_view_share.js | 811 +++++++++--------- .../integration/common/5a_user_role.js | 2 + .../integration/common/6b_downloadCsv.js | 2 - .../integration/common/6c_swagger_api.js | 450 +++++----- .../common/6d_language_validation.js | 7 +- .../common/6e_project_operations.js | 115 +-- .../integration/common/6g_base_share.js | 205 ++--- .../common/7a_create_project_from_excel.js | 536 ++++++------ scripts/cypress/support/commands.js | 64 ++ .../cypress/support/page_objects/mainPage.js | 26 + .../support/page_objects/navigation.js | 8 + 29 files changed, 2287 insertions(+), 1989 deletions(-) diff --git a/.gitignore b/.gitignore index 80af87ea84..0989a020e5 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,4 @@ mongod # Cypress #========= shared.json +/scripts/Cypress/screenshots \ No newline at end of file diff --git a/scripts/cypress/cypress.json b/scripts/cypress/cypress.json index ed881fc298..f1e83f0797 100644 --- a/scripts/cypress/cypress.json +++ b/scripts/cypress/cypress.json @@ -42,7 +42,8 @@ "host": "127.0.0.1", "user": "root", "password": "password" - } + }, + "screenshot": false }, "fixturesFolder": "scripts/cypress/fixtures", "integrationFolder": "scripts/cypress/integration", diff --git a/scripts/cypress/integration/common/00_pre_configurations.js b/scripts/cypress/integration/common/00_pre_configurations.js index 1daf8b2bf3..b1c712ec69 100644 --- a/scripts/cypress/integration/common/00_pre_configurations.js +++ b/scripts/cypress/integration/common/00_pre_configurations.js @@ -166,6 +166,7 @@ export const genTest = (apiType, dbType) => { const createProject = (proj) => { it(`Create ${proj.basic.name} project`, () => { + cy.snip("ProjectPage"); // click home button cy.get(".nc-noco-brand-icon").click(); diff --git a/scripts/cypress/integration/common/1a_table_operations.js b/scripts/cypress/integration/common/1a_table_operations.js index e5752c5cd8..a1050c521b 100644 --- a/scripts/cypress/integration/common/1a_table_operations.js +++ b/scripts/cypress/integration/common/1a_table_operations.js @@ -34,6 +34,8 @@ export const genTest = (apiType, dbType) => { it("Open Audit tab", () => { mainPage.navigationDraw(mainPage.AUDIT).click(); + cy.snip("AuditPage"); + // wait for column headers to appear // cy.get("thead > tr > th.caption").should("have.length", 5); diff --git a/scripts/cypress/integration/common/1b_table_column_operations.js b/scripts/cypress/integration/common/1b_table_column_operations.js index 558ebdc97c..8935fbe05d 100644 --- a/scripts/cypress/integration/common/1b_table_column_operations.js +++ b/scripts/cypress/integration/common/1b_table_column_operations.js @@ -1,165 +1,176 @@ import { mainPage } from "../../support/page_objects/mainPage"; import { - isTestSuiteActive, - isXcdb, + isTestSuiteActive, + isXcdb, } from "../../support/page_objects/projectConstants"; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; - - function addNewRow(index, cellValue) { - cy.get(".nc-add-new-row-btn:visible").should("exist"); - cy.get(".nc-add-new-row-btn").click({ force: true }); - cy.get("#data-table-form-Title > input").first().type(cellValue); - cy.getActiveModal() - .find("button") - .contains("Save Row") - .click({ force: true }); - - cy.toastWait("updated successfully"); - mainPage.getCell("Title", index).contains(cellValue).should("exist"); - } - - describe(`${apiType.toUpperCase()} api - Table Column`, () => { - const name = "tablex"; - const colName = "column_name_a"; - const updatedColName = "updated_column_name"; - const randVal = "Test@1234.com"; - const updatedRandVal = "Updated@1234.com"; - - before(() => { - cy.createTable(name); + if (!isTestSuiteActive(apiType, dbType)) return; + + function addNewRow(index, cellValue) { + cy.get(".nc-add-new-row-btn:visible").should("exist"); + cy.get(".nc-add-new-row-btn").click({ force: true }); + cy.get("#data-table-form-Title > input").first().type(cellValue); + cy.snipActiveModal("Modal_AddNewRow"); + cy.getActiveModal() + .find("button") + .contains("Save Row") + .click({ force: true }); + + cy.toastWait("updated successfully"); + mainPage.getCell("Title", index).contains(cellValue).should("exist"); + } + + describe(`${apiType.toUpperCase()} api - Table Column`, () => { + const name = "tablex"; + const colName = "column_name_a"; + const updatedColName = "updated_column_name"; + const randVal = "Test@1234.com"; + const updatedRandVal = "Updated@1234.com"; + + before(() => { + cy.createTable(name); + }); + + // delete table + after(() => { + cy.deleteTable(name, dbType); + }); + + it("Create Table Column", () => { + cy.get(`.project-tab:contains(${name}):visible`).should("exist"); + mainPage.addColumn(colName, name); + + cy.get(`th:contains(${colName})`).should("exist"); + }); + + // edit the newly created column + it("Edit table column - change datatype", () => { + if (!isXcdb()) { + cy.get(`th:contains(${colName}) .mdi-menu-down`) + .trigger("mouseover", { force: true }) + .click({ force: true }); + + cy.get(".nc-column-edit").click(); + + // change column type and verify + cy.get(".nc-ui-dt-dropdown").click(); + cy.contains("LongText").click(); + cy.get(".nc-col-create-or-edit-card").contains("Save").click(); + + cy.toastWait("Update table successful"); + + cy.get(`th[data-col="${colName}"] .mdi-text-subject`).should( + "exist" + ); + + cy.get(`th:contains(${colName}) .mdi-menu-down`) + .trigger("mouseover", { force: true }) + .click({ force: true }); + + cy.get(".nc-column-edit").click(); + } + }); + + // edit the newly created column + it("Edit table column - rename", () => { + cy.get(`th:contains(${colName}) .mdi-menu-down`) + .trigger("mouseover", { force: true }) + .click({ force: true }); + + cy.get(".nc-column-edit").click(); + + // rename column and verify + cy.get(".nc-column-name-input input").clear().type(updatedColName); + cy.get(".nc-col-create-or-edit-card").contains("Save").click(); + + cy.toastWait("Update table successful"); + + cy.get(`th:contains(${colName})`).should("not.exist"); + cy.get(`th:contains(${updatedColName})`).should("exist"); + }); + + // delete the newly created column + it("Delete table column", () => { + cy.get(`th:contains(${updatedColName})`).should("exist"); + + cy.get(`th:contains(${updatedColName}) .mdi-menu-down`) + .trigger("mouseover") + .click(); + + cy.get(".nc-column-delete").click(); + cy.get("button:contains(Confirm)").click(); + cy.toastWait("Update table successful"); + + cy.get(`th:contains(${updatedColName})`).should("not.exist"); + }); + + it("Add new row", () => { + addNewRow(1, randVal); + }); + + it("Update row", () => { + mainPage + .getRow(1) + .find(".nc-row-expand-icon") + .click({ force: true }); + cy.get("#data-table-form-Title > input") + .first() + .clear() + .type(updatedRandVal); + cy.getActiveModal() + .find("button") + .contains("Save Row") + .click({ force: true }); + + cy.toastWait("updated successfully"); + + mainPage.getCell("Title", 1).contains(randVal).should("not.exist"); + mainPage + .getCell("Title", 1) + .contains(updatedRandVal) + .should("exist"); + }); + + it("Delete row", () => { + mainPage + .getCell("Title", 1) + .contains(updatedRandVal) + .rightclick({ force: true }); + + // delete row + cy.getActiveMenu() + .find('.v-list-item:contains("Delete Row")') + .first() + .click({ force: true }); + // cy.toastWait('Deleted row successfully') + cy.get("td").contains(randVal).should("not.exist"); + }); + + it("Select all row check-box validation", () => { + // add multiple rows + addNewRow(1, "a1"); + addNewRow(2, "a2"); + addNewRow(3, "a3"); + addNewRow(4, "a4"); + addNewRow(5, "a5"); + + // check-box, select-all. 0 indicates table header + mainPage + .getRow(0) + .find(".mdi-checkbox-blank-outline") + .click({ force: true }); + + // delete selected rows + mainPage.getCell("Title", 1).rightclick({ force: true }); + cy.getActiveMenu() + .contains("Delete Selected Row") + .click({ force: true }); + + // verify if everything is wiped off + mainPage.getCell("Title", 1).contains("a1").should("not.exist"); + }); }); - - // delete table - after(() => { - cy.deleteTable(name, dbType); - }); - - it("Create Table Column", () => { - cy.get(`.project-tab:contains(${name}):visible`).should("exist"); - mainPage.addColumn(colName, name); - - cy.get(`th:contains(${colName})`).should("exist"); - }); - - // edit the newly created column - it("Edit table column - change datatype", () => { - if (!isXcdb()) { - cy.get(`th:contains(${colName}) .mdi-menu-down`) - .trigger("mouseover", { force: true }) - .click({ force: true }); - - cy.get(".nc-column-edit").click(); - - // change column type and verify - cy.get(".nc-ui-dt-dropdown").click(); - cy.contains("LongText").click(); - cy.get(".nc-col-create-or-edit-card").contains("Save").click(); - - cy.toastWait("Update table successful"); - - cy.get(`th[data-col="${colName}"] .mdi-text-subject`).should("exist"); - - cy.get(`th:contains(${colName}) .mdi-menu-down`) - .trigger("mouseover", { force: true }) - .click({ force: true }); - - cy.get(".nc-column-edit").click(); - } - }); - - // edit the newly created column - it("Edit table column - rename", () => { - cy.get(`th:contains(${colName}) .mdi-menu-down`) - .trigger("mouseover", { force: true }) - .click({ force: true }); - - cy.get(".nc-column-edit").click(); - - // rename column and verify - cy.get(".nc-column-name-input input").clear().type(updatedColName); - cy.get(".nc-col-create-or-edit-card").contains("Save").click(); - - cy.toastWait("Update table successful"); - - cy.get(`th:contains(${colName})`).should("not.exist"); - cy.get(`th:contains(${updatedColName})`).should("exist"); - }); - - // delete the newly created column - it("Delete table column", () => { - cy.get(`th:contains(${updatedColName})`).should("exist"); - - cy.get(`th:contains(${updatedColName}) .mdi-menu-down`) - .trigger("mouseover") - .click(); - - cy.get(".nc-column-delete").click(); - cy.get("button:contains(Confirm)").click(); - cy.toastWait("Update table successful"); - - cy.get(`th:contains(${updatedColName})`).should("not.exist"); - }); - - it("Add new row", () => { - addNewRow(1, randVal); - }); - - it("Update row", () => { - mainPage.getRow(1).find(".nc-row-expand-icon").click({ force: true }); - cy.get("#data-table-form-Title > input") - .first() - .clear() - .type(updatedRandVal); - cy.getActiveModal() - .find("button") - .contains("Save Row") - .click({ force: true }); - - cy.toastWait("updated successfully"); - - mainPage.getCell("Title", 1).contains(randVal).should("not.exist"); - mainPage.getCell("Title", 1).contains(updatedRandVal).should("exist"); - }); - - it("Delete row", () => { - mainPage - .getCell("Title", 1) - .contains(updatedRandVal) - .rightclick({ force: true }); - - // delete row - cy.getActiveMenu() - .find('.v-list-item:contains("Delete Row")') - .first() - .click({ force: true }); - // cy.toastWait('Deleted row successfully') - cy.get("td").contains(randVal).should("not.exist"); - }); - - it("Select all row check-box validation", () => { - // add multiple rows - addNewRow(1, "a1"); - addNewRow(2, "a2"); - addNewRow(3, "a3"); - addNewRow(4, "a4"); - addNewRow(5, "a5"); - - // check-box, select-all. 0 indicates table header - mainPage - .getRow(0) - .find(".mdi-checkbox-blank-outline") - .click({ force: true }); - - // delete selected rows - mainPage.getCell("Title", 1).rightclick({ force: true }); - cy.getActiveMenu().contains("Delete Selected Row").click({ force: true }); - - // verify if everything is wiped off - mainPage.getCell("Title", 1).contains("a1").should("not.exist"); - }); - }); }; /** diff --git a/scripts/cypress/integration/common/1d_pg_table_view_drag_drop_reorder.js b/scripts/cypress/integration/common/1d_pg_table_view_drag_drop_reorder.js index 4658129bf3..3675cf331f 100644 --- a/scripts/cypress/integration/common/1d_pg_table_view_drag_drop_reorder.js +++ b/scripts/cypress/integration/common/1d_pg_table_view_drag_drop_reorder.js @@ -87,6 +87,8 @@ export const genTest = (apiType, dbType) => { // click on 'Grid/Gallery' button on Views bar cy.get(`.nc-create-${viewType}-view`).click(); + cy.snipActiveModal(`Modal_createView_${viewType}`); + // Pop up window, click Submit (accepting default name for view) cy.getActiveModal().find("button:contains(Submit)").click(); diff --git a/scripts/cypress/integration/common/1d_table_view_drag_drop_reorder.js b/scripts/cypress/integration/common/1d_table_view_drag_drop_reorder.js index dfe7244c27..264ef5b924 100644 --- a/scripts/cypress/integration/common/1d_table_view_drag_drop_reorder.js +++ b/scripts/cypress/integration/common/1d_table_view_drag_drop_reorder.js @@ -80,6 +80,8 @@ export const genTest = (apiType, dbType) => { // click on 'Grid/Gallery' button on Views bar cy.get(`.nc-create-${viewType}-view`).click(); + cy.snipActiveModal(`Modal_createView_${viewType}`); + // Pop up window, click Submit (accepting default name for view) cy.getActiveModal().find("button:contains(Submit)").click(); diff --git a/scripts/cypress/integration/common/1e_meta_sync.js b/scripts/cypress/integration/common/1e_meta_sync.js index 861da39c44..f06cd9cc60 100644 --- a/scripts/cypress/integration/common/1e_meta_sync.js +++ b/scripts/cypress/integration/common/1e_meta_sync.js @@ -1,165 +1,174 @@ import { mainPage } from "../../support/page_objects/mainPage"; import { loginPage } from "../../support/page_objects/navigation"; import { - getCurrentMode, - getProjectString, - isTestSuiteActive, - isXcdb, + getCurrentMode, + getProjectString, + isTestSuiteActive, + isXcdb, } from "../../support/page_objects/projectConstants"; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; - - let projPrefix = `sakila.`; - let dbCmd = `queryDb`; - let tblDisplayPrefix = ``; - - describe(`${apiType.toUpperCase()} api - Meta Sync`, () => { - // Run once before test- create project (rest/graphql) - // - before(() => { - if (isXcdb()) { - cy.log(getProjectString()); - projPrefix = `nc_${getProjectString()}__`; - dbCmd = `sqliteExec`; - tblDisplayPrefix = `nc_${getProjectString()}__`; - } - mainPage.openMetaTab(); + if (!isTestSuiteActive(apiType, dbType)) return; + + let projPrefix = `sakila.`; + let dbCmd = `queryDb`; + let tblDisplayPrefix = ``; + + describe(`${apiType.toUpperCase()} api - Meta Sync`, () => { + // Run once before test- create project (rest/graphql) + // + before(() => { + if (isXcdb()) { + cy.log(getProjectString()); + projPrefix = `nc_${getProjectString()}__`; + dbCmd = `sqliteExec`; + tblDisplayPrefix = `nc_${getProjectString()}__`; + } + mainPage.openMetaTab(); + }); + + after(() => { + mainPage.closeMetaTab(); + }); + + it(`Create table`, () => { + // Create Table + cy.task( + dbCmd, + `CREATE TABLE ${projPrefix}table1 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))` + ); + cy.task( + dbCmd, + `CREATE TABLE ${projPrefix}table2 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))` + ); + mainPage.metaSyncValidate(`${tblDisplayPrefix}table1`, "New table"); + }); + + it(`Add relation`, () => { + // working with relations in sqlite requires table to be deleted & recreated + // + if (!isXcdb()) { + // Add relation (FK) + cy.task( + dbCmd, + `ALTER TABLE ${projPrefix}table1 ADD INDEX fk1_idx (col1 ASC) VISIBLE` + ); + cy.task( + dbCmd, + `ALTER TABLE ${projPrefix}table1 ADD CONSTRAINT fk1 FOREIGN KEY (col1) REFERENCES ${projPrefix}table2 (id) ON DELETE NO ACTION ON UPDATE NO ACTION` + ); + mainPage.metaSyncValidate( + `${tblDisplayPrefix}table1`, + "New relation added" + ); + } + }); + + it(`Remove relation`, () => { + // working with relations in sqlite requires table to be deleted & recreated + // + if (!isXcdb()) { + // Remove relation (FK) + cy.task( + dbCmd, + `ALTER TABLE ${projPrefix}table1 DROP FOREIGN KEY fk1` + ); + cy.task( + dbCmd, + `ALTER TABLE ${projPrefix}table1 DROP INDEX fk1_idx` + ); + mainPage.metaSyncValidate( + `${tblDisplayPrefix}table1`, + "Relation removed" + ); + } + }); + + it(`Add column`, () => { + // Add Column + let queryString = `ALTER TABLE ${projPrefix}table1 ADD COLUMN newCol VARCHAR(45) NULL AFTER id`; + if (isXcdb()) + queryString = `ALTER TABLE ${projPrefix}table1 ADD COLUMN newCol TEXT NULL`; + cy.task(dbCmd, queryString); + mainPage.metaSyncValidate( + `${tblDisplayPrefix}table1`, + "New column(newCol)" + ); + }); + + it(`Rename column`, () => { + // Rename Column + let queryString = `ALTER TABLE ${projPrefix}table1 CHANGE COLUMN newCol newColName VARCHAR(45) NULL DEFAULT NULL`; + if (isXcdb()) + queryString = `ALTER TABLE ${projPrefix}table1 RENAME COLUMN newCol TO newColName`; + cy.task(dbCmd, queryString); + mainPage.metaSyncValidate( + `${tblDisplayPrefix}table1`, + "New column(newColName), Column removed(newCol)" + ); + }); + + it(`Delete column`, () => { + // Remove Column + // to be fixed for SQLITE + if (!isXcdb()) { + cy.task( + dbCmd, + `ALTER TABLE ${projPrefix}table1 DROP COLUMN newColName` + ); + mainPage.metaSyncValidate( + `${tblDisplayPrefix}table1`, + "Column removed(newColName)" + ); + } + }); + + it(`Delete table`, () => { + // DROP TABLE + cy.task(dbCmd, `DROP TABLE ${projPrefix}table1`); + cy.task(dbCmd, `DROP TABLE ${projPrefix}table2`); + mainPage.metaSyncValidate( + `${tblDisplayPrefix}table1`, + "Table removed" + ); + }); + + it(`Hide, Filter, Sort`, () => { + cy.task( + dbCmd, + `CREATE TABLE ${projPrefix}table1 (id INT NOT NULL, col1 INT NULL, col2 INT NULL, col3 INT NULL, col4 INT NULL, PRIMARY KEY (id))` + ); + cy.task( + dbCmd, + `INSERT INTO ${projPrefix}table1 (id, col1, col2, col3, col4) VALUES (1,1,1,1,1), (2,2,2,2,2), (3,3,3,3,3), (4,4,4,4,4), (5,5,5,5,5), (6,6,6,6,6), (7,7,7,7,7), (8,8,8,8,8), (9,9,9,9,9);` + ); + mainPage.metaSyncValidate(`${tblDisplayPrefix}table1`, "New table"); + mainPage.closeMetaTab(); + + cy.openTableTab("Table1", 9); + mainPage.hideField("Col1"); + mainPage.sortField("Col1", "Z -> A"); + mainPage.filterField(`Col1`, ">=", "5"); + cy.get(".nc-grid-row").should("have.length", 5); + cy.closeTableTab("Table1"); + }); + + it(`Verify`, () => { + mainPage.openMetaTab(); + // Rename Column + let queryString = `ALTER TABLE ${projPrefix}table1 CHANGE COLUMN col1 newCol INT NULL DEFAULT NULL`; + if (isXcdb()) + queryString = `ALTER TABLE ${projPrefix}table1 RENAME COLUMN col1 TO newCol`; + cy.task(dbCmd, queryString); + mainPage.metaSyncValidate( + `${tblDisplayPrefix}table1`, + "New column(newCol), Column removed(col1)" + ); + + cy.openTableTab("Table1", 9); + cy.deleteTable("Table1", dbType); + }); }); - - after(() => { - mainPage.closeMetaTab(); - }); - - it(`Create table`, () => { - // Create Table - cy.task( - dbCmd, - `CREATE TABLE ${projPrefix}table1 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))` - ); - cy.task( - dbCmd, - `CREATE TABLE ${projPrefix}table2 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))` - ); - mainPage.metaSyncValidate(`${tblDisplayPrefix}table1`, "New table"); - }); - - it(`Add relation`, () => { - // working with relations in sqlite requires table to be deleted & recreated - // - if (!isXcdb()) { - // Add relation (FK) - cy.task( - dbCmd, - `ALTER TABLE ${projPrefix}table1 ADD INDEX fk1_idx (col1 ASC) VISIBLE` - ); - cy.task( - dbCmd, - `ALTER TABLE ${projPrefix}table1 ADD CONSTRAINT fk1 FOREIGN KEY (col1) REFERENCES ${projPrefix}table2 (id) ON DELETE NO ACTION ON UPDATE NO ACTION` - ); - mainPage.metaSyncValidate( - `${tblDisplayPrefix}table1`, - "New relation added" - ); - } - }); - - it(`Remove relation`, () => { - // working with relations in sqlite requires table to be deleted & recreated - // - if (!isXcdb()) { - // Remove relation (FK) - cy.task(dbCmd, `ALTER TABLE ${projPrefix}table1 DROP FOREIGN KEY fk1`); - cy.task(dbCmd, `ALTER TABLE ${projPrefix}table1 DROP INDEX fk1_idx`); - mainPage.metaSyncValidate( - `${tblDisplayPrefix}table1`, - "Relation removed" - ); - } - }); - - it(`Add column`, () => { - // Add Column - let queryString = `ALTER TABLE ${projPrefix}table1 ADD COLUMN newCol VARCHAR(45) NULL AFTER id`; - if (isXcdb()) - queryString = `ALTER TABLE ${projPrefix}table1 ADD COLUMN newCol TEXT NULL`; - cy.task(dbCmd, queryString); - mainPage.metaSyncValidate( - `${tblDisplayPrefix}table1`, - "New column(newCol)" - ); - }); - - it(`Rename column`, () => { - // Rename Column - let queryString = `ALTER TABLE ${projPrefix}table1 CHANGE COLUMN newCol newColName VARCHAR(45) NULL DEFAULT NULL`; - if (isXcdb()) - queryString = `ALTER TABLE ${projPrefix}table1 RENAME COLUMN newCol TO newColName`; - cy.task(dbCmd, queryString); - mainPage.metaSyncValidate( - `${tblDisplayPrefix}table1`, - "New column(newColName), Column removed(newCol)" - ); - }); - - it(`Delete column`, () => { - // Remove Column - // to be fixed for SQLITE - if (!isXcdb()) { - cy.task( - dbCmd, - `ALTER TABLE ${projPrefix}table1 DROP COLUMN newColName` - ); - mainPage.metaSyncValidate( - `${tblDisplayPrefix}table1`, - "Column removed(newColName)" - ); - } - }); - - it(`Delete table`, () => { - // DROP TABLE - cy.task(dbCmd, `DROP TABLE ${projPrefix}table1`); - cy.task(dbCmd, `DROP TABLE ${projPrefix}table2`); - mainPage.metaSyncValidate(`${tblDisplayPrefix}table1`, "Table removed"); - }); - - it(`Hide, Filter, Sort`, () => { - cy.task( - dbCmd, - `CREATE TABLE ${projPrefix}table1 (id INT NOT NULL, col1 INT NULL, col2 INT NULL, col3 INT NULL, col4 INT NULL, PRIMARY KEY (id))` - ); - cy.task( - dbCmd, - `INSERT INTO ${projPrefix}table1 (id, col1, col2, col3, col4) VALUES (1,1,1,1,1), (2,2,2,2,2), (3,3,3,3,3), (4,4,4,4,4), (5,5,5,5,5), (6,6,6,6,6), (7,7,7,7,7), (8,8,8,8,8), (9,9,9,9,9);` - ); - mainPage.metaSyncValidate(`${tblDisplayPrefix}table1`, "New table"); - mainPage.closeMetaTab(); - - cy.openTableTab("Table1", 9); - mainPage.hideField("Col1"); - mainPage.sortField("Col1", "Z -> A"); - mainPage.filterField(`Col1`, ">=", "5"); - cy.get(".nc-grid-row").should("have.length", 5); - cy.closeTableTab("Table1"); - }); - - it(`Verify`, () => { - mainPage.openMetaTab(); - // Rename Column - let queryString = `ALTER TABLE ${projPrefix}table1 CHANGE COLUMN col1 newCol INT NULL DEFAULT NULL`; - if (isXcdb()) - queryString = `ALTER TABLE ${projPrefix}table1 RENAME COLUMN col1 TO newCol`; - cy.task(dbCmd, queryString); - mainPage.metaSyncValidate( - `${tblDisplayPrefix}table1`, - "New column(newCol), Column removed(col1)" - ); - - cy.openTableTab("Table1", 9); - cy.deleteTable("Table1", dbType); - }); - }); }; /** diff --git a/scripts/cypress/integration/common/2a_table_with_belongs_to_colulmn.js b/scripts/cypress/integration/common/2a_table_with_belongs_to_colulmn.js index 944f53f445..5bdb056fd7 100644 --- a/scripts/cypress/integration/common/2a_table_with_belongs_to_colulmn.js +++ b/scripts/cypress/integration/common/2a_table_with_belongs_to_colulmn.js @@ -1,60 +1,72 @@ import { isTestSuiteActive } from "../../support/page_objects/projectConstants"; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; + if (!isTestSuiteActive(apiType, dbType)) return; - describe(`${apiType.toUpperCase()} api - Table: belongs to, link record`, () => { - before(() => { - cy.openTableTab("Country", 25); - }); + describe(`${apiType.toUpperCase()} api - Table: belongs to, link record`, () => { + before(() => { + cy.openTableTab("Country", 25); + }); - after(() => { - cy.closeTableTab("Country"); - }); + after(() => { + cy.closeTableTab("Country"); + }); - it("Table column header, URL validation", () => { - // column name validation - cy.get(`.project-tab:contains(Country):visible`).should("exist"); - // URL validation - cy.url().should("contain", `name=Country`); - }); + it("Table column header, URL validation", () => { + // column name validation + cy.get(`.project-tab:contains(Country):visible`).should("exist"); + // URL validation + cy.url().should("contain", `name=Country`); + }); - it("Expand belongs-to column", () => { - // expand first row - cy.get('td[data-col="Country => City"] div:visible', { timeout: 12000 }) - .first() - .click(); - cy.get('td[data-col="Country => City"] div .mdi-arrow-expand:visible') - .first() - .click(); - }); + it("Expand belongs-to column", () => { + // expand first row + cy.get('td[data-col="Country => City"] div:visible', { + timeout: 12000, + }) + .first() + .click(); + cy.get( + 'td[data-col="Country => City"] div .mdi-arrow-expand:visible' + ) + .first() + .click(); + + cy.snipActiveModal("Modal_BelongsTo"); + }); + + it("Expand Link record, validate", () => { + cy.getActiveModal() + .find("button:contains(Link to 'City')") + .click() + .then(() => { + cy.snipActiveModal("Modal_BT_LinkRecord"); - it("Expand Link record, validate", () => { - cy.getActiveModal() - .find("button:contains(Link to 'City')") - .click() - .then(() => { - // Link record form validation - cy.getActiveModal().contains("Link Record").should("exist"); - cy.getActiveModal().find("button.mdi-reload").should("exist"); - cy.getActiveModal() - .find('button:contains("New Record")') - .should("exist"); - cy.getActiveModal() - .find(".child-card") - .eq(0) - .contains("A Corua (La Corua)") - .should("exist"); + // Link record form validation + cy.getActiveModal().contains("Link Record").should("exist"); + cy.getActiveModal() + .find("button.mdi-reload") + .should("exist"); + cy.getActiveModal() + .find('button:contains("New Record")') + .should("exist"); + cy.getActiveModal() + .find(".child-card") + .eq(0) + .contains("A Corua (La Corua)") + .should("exist"); - cy.getActiveModal() - .find("button.mdi-close") - .click() - .then(() => { - cy.getActiveModal().find("button.mdi-close").click(); - }); + cy.getActiveModal() + .find("button.mdi-close") + .click() + .then(() => { + cy.getActiveModal() + .find("button.mdi-close") + .click(); + }); + }); }); }); - }); }; /** diff --git a/scripts/cypress/integration/common/2b_table_with_m2m_column.js b/scripts/cypress/integration/common/2b_table_with_m2m_column.js index 6bf0ed6aaa..0debb3c78d 100644 --- a/scripts/cypress/integration/common/2b_table_with_m2m_column.js +++ b/scripts/cypress/integration/common/2b_table_with_m2m_column.js @@ -1,88 +1,97 @@ import { isTestSuiteActive } from "../../support/page_objects/projectConstants"; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; + if (!isTestSuiteActive(apiType, dbType)) return; - describe(`${apiType.toUpperCase()} api - M2M Column validation`, () => { - before(() => { - cy.openTableTab("Actor", 25); - }); + describe(`${apiType.toUpperCase()} api - M2M Column validation`, () => { + before(() => { + cy.openTableTab("Actor", 25); + }); - after(() => { - cy.closeTableTab("Actor"); - }); + after(() => { + cy.closeTableTab("Actor"); + }); - it("Table column header, URL validation", () => { - // column name validation - cy.get(`.project-tab:contains(Actor):visible`).should("exist"); - // URL validation - cy.url().should("contain", `name=Actor`); - }); + it("Table column header, URL validation", () => { + // column name validation + cy.get(`.project-tab:contains(Actor):visible`).should("exist"); + // URL validation + cy.url().should("contain", `name=Actor`); + }); - it("Expand m2m column", () => { - // expand first row - cy.get('td[data-col="Actor <=> Film"] div', { timeout: 12000 }) - .first() - .click({ force: true }); - cy.get('td[data-col="Actor <=> Film"] div .mdi-arrow-expand') - .first() - .click({ force: true }); + it("Expand m2m column", () => { + // expand first row + cy.get('td[data-col="Actor <=> Film"] div', { timeout: 12000 }) + .first() + .click({ force: true }); + cy.get('td[data-col="Actor <=> Film"] div .mdi-arrow-expand') + .first() + .click({ force: true }); - // validations - cy.getActiveModal().contains("Film").should("exist"); - cy.getActiveModal().find("button.mdi-reload").should("exist"); - cy.getActiveModal() - .find("button:contains(Link to 'Film')") - .should("exist"); - cy.getActiveModal() - .find(".child-card") - .eq(0) - .contains("ACADEMY DINOSAUR") - .should("exist"); - }); + cy.snipActiveModal("Modal_ManyToMany"); - it('Expand "Link to" record, validate', () => { - cy.getActiveModal() - .find("button:contains(Link to 'Film')") - .click() - .then(() => { - // Link record form validation - cy.getActiveModal().contains("Link Record").should("exist"); - cy.getActiveModal().find("button.mdi-reload").should("exist"); - cy.getActiveModal() - .find('button:contains("New Record")') - .should("exist"); - cy.getActiveModal() - .find(".child-card") - .eq(0) - .contains("ACE GOLDFINGER") - .should("exist"); - cy.get("body").type("{esc}"); + // validations + cy.getActiveModal().contains("Film").should("exist"); + cy.getActiveModal().find("button.mdi-reload").should("exist"); + cy.getActiveModal() + .find("button:contains(Link to 'Film')") + .should("exist"); + cy.getActiveModal() + .find(".child-card") + .eq(0) + .contains("ACADEMY DINOSAUR") + .should("exist"); + }); + + it('Expand "Link to" record, validate', () => { + cy.getActiveModal() + .find("button:contains(Link to 'Film')") + .click() + .then(() => { + cy.snipActiveModal("Modal_M2M_LinkToRecord"); + // Link record form validation + cy.getActiveModal().contains("Link Record").should("exist"); + cy.getActiveModal() + .find("button.mdi-reload") + .should("exist"); + cy.getActiveModal() + .find('button:contains("New Record")') + .should("exist"); + cy.getActiveModal() + .find(".child-card") + .eq(0) + .contains("ACE GOLDFINGER") + .should("exist"); + cy.get("body").type("{esc}"); + }); }); - }); - it("Expand first linked card, validate", () => { - cy.getActiveModal() - .find(".child-card") - .eq(0) - .contains("ACADEMY DINOSAUR", { timeout: 2000 }) - .click() - .then(() => { - // Link card validation - cy.getActiveModal() - .find("h5") - .contains("ACADEMY DINOSAUR") - .should("exist"); - cy.getActiveModal() - .find('button:contains("Save Row")') - .should("exist"); - cy.getActiveModal().find('button:contains("Cancel")').should("exist"); + it("Expand first linked card, validate", () => { + cy.getActiveModal() + .find(".child-card") + .eq(0) + .contains("ACADEMY DINOSAUR", { timeout: 2000 }) + .click() + .then(() => { + // Link card validation + cy.getActiveModal() + .find("h5") + .contains("ACADEMY DINOSAUR") + .should("exist"); + cy.getActiveModal() + .find('button:contains("Save Row")') + .should("exist"); + cy.getActiveModal() + .find('button:contains("Cancel")') + .should("exist"); - cy.getActiveModal().find('button:contains("Cancel")').click(); - cy.getActiveModal().find("button.mdi-close").click(); + cy.getActiveModal() + .find('button:contains("Cancel")') + .click(); + cy.getActiveModal().find("button.mdi-close").click(); + }); }); }); - }); }; /** diff --git a/scripts/cypress/integration/common/3a_filter_sort_fields_operations.js b/scripts/cypress/integration/common/3a_filter_sort_fields_operations.js index 11af574155..fb566a9b33 100644 --- a/scripts/cypress/integration/common/3a_filter_sort_fields_operations.js +++ b/scripts/cypress/integration/common/3a_filter_sort_fields_operations.js @@ -2,212 +2,221 @@ import { mainPage } from "../../support/page_objects/mainPage"; import { isTestSuiteActive } from "../../support/page_objects/projectConstants"; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; - - describe(`${apiType.toUpperCase()} api - Filter, Fields, Sort`, () => { - before(() => { - // open country table - cy.openTableTab("Country", 25); - }); - - after(() => { - cy.closeTableTab("Country"); - }); - - describe(`Pagination`, () => { - // check pagination - it("Check country table - Pagination", () => { - cy.get(".nc-pagination").should("exist"); - - // verify > pagination option - mainPage.getPagination(">").click(); - mainPage - .getPagination(2) - .should("have.class", "v-pagination__item--active"); - - // verify < pagination option - mainPage.getPagination("<").click(); - mainPage - .getPagination(1) - .should("have.class", "v-pagination__item--active"); - }); - }); - - describe(`Row operations`, () => { - // create new row using + button in header - // - it("Add row using tool header button", () => { - // add a row to end of Country table - cy.get(".nc-add-new-row-btn").click(); - cy.get("#data-table-form-Country > input").first().type("Test Country"); - cy.contains("Save Row").filter("button").click(); - - cy.toastWait("updated successfully"); - - // verify - mainPage.getPagination(5).click(); - mainPage - .getCell("Country", 10) - .contains("Test Country") - .should("exist"); - }); - - // delete slingle row - // - it("Delete row", () => { - // delete row added in previous step - mainPage.getCell("Country", 10).rightclick(); - cy.getActiveMenu().contains("Delete Row").click(); - - // cy.toastWait('Deleted row successfully') - - // verify - mainPage.getCell("Country", 10).should("not.exist"); - }); - - // create new row using right click menu option - // - it("Add row using rightclick menu option", () => { - mainPage.getCell("Country", 9).rightclick({ force: true }); - cy.getActiveMenu().contains("Insert New Row").click({ force: true }); - mainPage - .getCell("Country", 10) - .dblclick() - .find("input") - .type("Test Country-1{enter}"); - - // cy.toastWait('saved successfully') - - mainPage.getCell("Country", 10).rightclick({ force: true }); - cy.getActiveMenu().contains("Insert New Row").click({ force: true }); - mainPage - .getCell("Country", 11) - .dblclick() - .find("input") - .type("Test Country-2{enter}"); - - // cy.toastWait('saved successfully') - - // verify - mainPage - .getCell("Country", 10) - .contains("Test Country-1") - .should("exist"); - mainPage - .getCell("Country", 11) - .contains("Test Country-2") - .should("exist"); - }); - - // delete selected rows (multiple) - // - it("Delete Selected", () => { - mainPage - .getRow(10) - .find(".mdi-checkbox-blank-outline") - .click({ force: true }); - mainPage - .getRow(11) - .find(".mdi-checkbox-blank-outline") - .click({ force: true }); - - mainPage.getCell("Country", 10).rightclick({ force: true }); - cy.getActiveMenu() - .contains("Delete Selected Row") - .click({ force: true }); - - // cy.toastWait('Deleted 2 selected rows successfully') - - // verify - mainPage.getCell("Country", 10).should("not.exist"); - mainPage.getCell("Country", 11).should("not.exist"); - - mainPage.getPagination(1).click(); - }); - }); - - describe(`Sort operations`, () => { - it("Enable sort", () => { - mainPage.sortField('Country', "Z -> A") - - // Sort menu operations (Country Column, Z->A) - // cy.get(".nc-sort-menu-btn").click(); - // cy.contains("Add Sort Option").click(); - // cy.get(".nc-sort-field-select div").first().click(); - // cy.get( - // ".menuable__content__active .v-list-item:contains(Country)" - // ).click(); - // cy.get(".nc-sort-dir-select div").first().click(); - // cy.get( - // '.menuable__content__active .v-list-item:contains("Z -> A")' - // ).click(); - - cy.contains("Zambia").should("exist"); - }); - - it("Disable sort", () => { - // remove sort and validate - // cy.get(".nc-sort-item-remove-btn").click(); - mainPage.clearSort(); - cy.contains("Zambia").should("not.exist"); - }); - }); - - describe("Field Operation", () => { - it("Hide field", () => { - cy.get("th:contains(LastUpdate)").should("be.visible"); - - // toggle and confirm it's hidden - // cy.get(".nc-fields-menu-btn").click(); - // cy.get( - // ".menuable__content__active .v-list-item label:contains(LastUpdate)" - // ).click(); - // cy.get(".nc-fields-menu-btn").click(); - mainPage.hideField('LastUpdate') - cy.get("th:contains(LastUpdate)").should("not.be.visible"); - }); - - it("Show field", () => { - // cy.get(".nc-fields-menu-btn").click(); - // cy.get( - // ".menuable__content__active .v-list-item label:contains(LastUpdate)" - // ).click(); - // cy.get(".nc-fields-menu-btn").click(); - mainPage.unhideField('LastUpdate') - cy.get("th:contains(LastUpdate)").should("be.visible"); - }); - }); - - describe("Filter operations", () => { - it("Create Filter", () => { - mainPage.filterField('Country', 'is equal', 'India'); - cy.get("td:contains(India)").should("exist"); - - // cy.get(".nc-filter-menu-btn").click(); - // cy.contains("Add Filter").click(); - - // cy.get(".nc-filter-field-select").last().click(); - // cy.getActiveMenu().find(".v-list-item:contains(Country)").click(); - // cy.get(".nc-filter-operation-select").last().click(); - // cy.getActiveMenu().find('.v-list-item:contains("is equal")').click(); - // cy.get(".nc-filter-value-select input:text").last().type("India"); - // cy.get(".nc-filter-menu-btn") - // .click() - // .then(() => { - // cy.get("td:contains(India)").should("exist"); - // }); - }); - - it("Delete Filter", () => { - // remove sort and check - mainPage.filterReset(); - // cy.get(".nc-filter-menu-btn").click(); - // cy.get(".nc-filter-item-remove-btn").click(); - // cy.get(".nc-filter-menu-btn").click(); - cy.contains("td:contains(India)").should("not.exist"); - }); + if (!isTestSuiteActive(apiType, dbType)) return; + + describe(`${apiType.toUpperCase()} api - Filter, Fields, Sort`, () => { + before(() => { + // open country table + cy.openTableTab("Country", 25); + }); + + after(() => { + cy.closeTableTab("Country"); + }); + + describe(`Pagination`, () => { + // check pagination + it("Check country table - Pagination", () => { + cy.get(".nc-pagination").should("exist"); + + // verify > pagination option + mainPage.getPagination(">").click(); + mainPage + .getPagination(2) + .should("have.class", "v-pagination__item--active"); + + // verify < pagination option + mainPage.getPagination("<").click(); + mainPage + .getPagination(1) + .should("have.class", "v-pagination__item--active"); + }); + }); + + describe(`Row operations`, () => { + // create new row using + button in header + // + it("Add row using tool header button", () => { + // add a row to end of Country table + cy.get(".nc-add-new-row-btn").click(); + cy.get("#data-table-form-Country > input") + .first() + .type("Test Country"); + cy.contains("Save Row").filter("button").click(); + + cy.toastWait("updated successfully"); + + // verify + mainPage.getPagination(5).click(); + mainPage + .getCell("Country", 10) + .contains("Test Country") + .should("exist"); + }); + + // delete slingle row + // + it("Delete row", () => { + // delete row added in previous step + mainPage.getCell("Country", 10).rightclick(); + cy.getActiveMenu().contains("Delete Row").click(); + + // cy.toastWait('Deleted row successfully') + + // verify + mainPage.getCell("Country", 10).should("not.exist"); + }); + + // create new row using right click menu option + // + it("Add row using rightclick menu option", () => { + mainPage.getCell("Country", 9).rightclick({ force: true }); + + cy.snipActiveMenu("Menu_GridRightClick"); + + cy.getActiveMenu() + .contains("Insert New Row") + .click({ force: true }); + mainPage + .getCell("Country", 10) + .dblclick() + .find("input") + .type("Test Country-1{enter}"); + + // cy.toastWait('saved successfully') + + mainPage.getCell("Country", 10).rightclick({ force: true }); + cy.getActiveMenu() + .contains("Insert New Row") + .click({ force: true }); + mainPage + .getCell("Country", 11) + .dblclick() + .find("input") + .type("Test Country-2{enter}"); + + // cy.toastWait('saved successfully') + + // verify + mainPage + .getCell("Country", 10) + .contains("Test Country-1") + .should("exist"); + mainPage + .getCell("Country", 11) + .contains("Test Country-2") + .should("exist"); + }); + + // delete selected rows (multiple) + // + it("Delete Selected", () => { + mainPage + .getRow(10) + .find(".mdi-checkbox-blank-outline") + .click({ force: true }); + mainPage + .getRow(11) + .find(".mdi-checkbox-blank-outline") + .click({ force: true }); + + mainPage.getCell("Country", 10).rightclick({ force: true }); + cy.getActiveMenu() + .contains("Delete Selected Row") + .click({ force: true }); + + // cy.toastWait('Deleted 2 selected rows successfully') + + // verify + mainPage.getCell("Country", 10).should("not.exist"); + mainPage.getCell("Country", 11).should("not.exist"); + + mainPage.getPagination(1).click(); + }); + }); + + describe(`Sort operations`, () => { + it("Enable sort", () => { + mainPage.sortField("Country", "Z -> A"); + + // Sort menu operations (Country Column, Z->A) + // cy.get(".nc-sort-menu-btn").click(); + // cy.contains("Add Sort Option").click(); + // cy.get(".nc-sort-field-select div").first().click(); + // cy.get( + // ".menuable__content__active .v-list-item:contains(Country)" + // ).click(); + // cy.get(".nc-sort-dir-select div").first().click(); + // cy.get( + // '.menuable__content__active .v-list-item:contains("Z -> A")' + // ).click(); + + cy.contains("Zambia").should("exist"); + }); + + it("Disable sort", () => { + // remove sort and validate + // cy.get(".nc-sort-item-remove-btn").click(); + mainPage.clearSort(); + cy.contains("Zambia").should("not.exist"); + }); + }); + + describe("Field Operation", () => { + it("Hide field", () => { + cy.get("th:contains(LastUpdate)").should("be.visible"); + + // toggle and confirm it's hidden + // cy.get(".nc-fields-menu-btn").click(); + // cy.get( + // ".menuable__content__active .v-list-item label:contains(LastUpdate)" + // ).click(); + // cy.get(".nc-fields-menu-btn").click(); + mainPage.hideField("LastUpdate"); + cy.get("th:contains(LastUpdate)").should("not.be.visible"); + }); + + it("Show field", () => { + // cy.get(".nc-fields-menu-btn").click(); + // cy.get( + // ".menuable__content__active .v-list-item label:contains(LastUpdate)" + // ).click(); + // cy.get(".nc-fields-menu-btn").click(); + mainPage.unhideField("LastUpdate"); + cy.get("th:contains(LastUpdate)").should("be.visible"); + }); + }); + + describe("Filter operations", () => { + it("Create Filter", () => { + mainPage.filterField("Country", "is equal", "India"); + cy.get("td:contains(India)").should("exist"); + + // cy.get(".nc-filter-menu-btn").click(); + // cy.contains("Add Filter").click(); + + // cy.get(".nc-filter-field-select").last().click(); + // cy.getActiveMenu().find(".v-list-item:contains(Country)").click(); + // cy.get(".nc-filter-operation-select").last().click(); + // cy.getActiveMenu().find('.v-list-item:contains("is equal")').click(); + // cy.get(".nc-filter-value-select input:text").last().type("India"); + // cy.get(".nc-filter-menu-btn") + // .click() + // .then(() => { + // cy.get("td:contains(India)").should("exist"); + // }); + }); + + it("Delete Filter", () => { + // remove sort and check + mainPage.filterReset(); + // cy.get(".nc-filter-menu-btn").click(); + // cy.get(".nc-filter-item-remove-btn").click(); + // cy.get(".nc-filter-menu-btn").click(); + cy.contains("td:contains(India)").should("not.exist"); + }); + }); }); - }); }; /** diff --git a/scripts/cypress/integration/common/3b_formula_column.js b/scripts/cypress/integration/common/3b_formula_column.js index 10b23bf21a..344a9d8e65 100644 --- a/scripts/cypress/integration/common/3b_formula_column.js +++ b/scripts/cypress/integration/common/3b_formula_column.js @@ -49,6 +49,9 @@ export const genTest = (apiType, dbType) => { // Column data type: to be set to formula in this context cy.get(".nc-ui-dt-dropdown").click().type("Formula"); + + cy.snipActiveMenu("Formula"); + cy.getActiveMenu().contains("Formula").click({ force: true }); // Configure formula diff --git a/scripts/cypress/integration/common/3c_lookup_column.js b/scripts/cypress/integration/common/3c_lookup_column.js index 5b61f74d43..b0b9198763 100644 --- a/scripts/cypress/integration/common/3c_lookup_column.js +++ b/scripts/cypress/integration/common/3c_lookup_column.js @@ -1,101 +1,103 @@ import { isTestSuiteActive } from "../../support/page_objects/projectConstants"; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; - - describe(`${apiType.toUpperCase()} api - LookUp column`, () => { - // to retrieve few v-input nodes from their label - // - const fetchParentFromLabel = (label) => { - cy.get("label").contains(label).parents(".v-input").click(); - }; - - // Run once before test- create project (rest/graphql) - // - before(() => { - // open a table to work on views - // - cy.openTableTab("City", 25); + if (!isTestSuiteActive(apiType, dbType)) return; + + describe(`${apiType.toUpperCase()} api - LookUp column`, () => { + // to retrieve few v-input nodes from their label + // + const fetchParentFromLabel = (label) => { + cy.get("label").contains(label).parents(".v-input").click(); + }; + + // Run once before test- create project (rest/graphql) + // + before(() => { + // open a table to work on views + // + cy.openTableTab("City", 25); + }); + + after(() => { + cy.closeTableTab("City"); + }); + + // Routine to create a new look up column + // + const addLookUpColumn = (childTable, childCol) => { + // (+) icon at end of column header (to add a new column) + // opens up a pop up window + // + cy.get(".new-column-header").click(); + + // Redundant to feed column name. as alias is displayed & referred for + cy.get(".nc-column-name-input input").clear().type(childCol); + + // Column data type: to be set to lookup in this context + cy.get(".nc-ui-dt-dropdown").click(); + cy.getActiveMenu().contains("Lookup").click(); + + // Configure Child table & column names + fetchParentFromLabel("Child Table"); + cy.getActiveMenu().contains(childTable).click(); + + fetchParentFromLabel("Child column"); + cy.getActiveMenu().contains(childCol).click(); + + cy.snipActiveMenu("LookUp"); + + // click on Save + cy.get(".nc-col-create-or-edit-card").contains("Save").click(); + + // Verify if column exists. + // + cy.get(`th:contains(${childCol})`).should("exist"); + }; + + // routine to delete column + // + const deleteColumnByName = (childCol) => { + // verify if column exists before delete + cy.get(`th:contains(${childCol})`).should("exist"); + + // delete opiton visible on mouse-over + cy.get(`th:contains(${childCol}) .mdi-menu-down`) + .trigger("mouseover") + .click(); + + // delete/ confirm on pop-up + cy.get(".nc-column-delete").click(); + cy.getActiveModal().find("button:contains(Confirm)").click(); + + // validate if deleted (column shouldnt exist) + cy.get(`th:contains(${childCol})`).should("not.exist"); + }; + + /////////////////////////////////////////////////// + // Test case + + it("Add Lookup column (Address, PostalCode) & Delete", () => { + addLookUpColumn("Address", "PostalCode"); + + // Verify first entry, will be displayed as alias here 'childColumn (from childTable)' + cy.get(`tbody > :nth-child(1) > [data-col="PostalCode"]`) + .contains("4166") + .should("exist"); + + deleteColumnByName("PostalCode"); + }); + + it.skip("Add Lookup column (Country, CountryId) & Delete", () => { + addLookUpColumn("Country", "CountryId"); + + // Verify first entry, will be displayed as alias here 'childColumn (from childTable)' + cy.get(`tbody > :nth-child(1) > [data-col="CountryId"]`) + .contains("87") + .should("exist"); + + deleteColumnByName("CountryId"); + }); }); - - after(() => { - cy.closeTableTab("City"); - }); - - // Routine to create a new look up column - // - const addLookUpColumn = (childTable, childCol) => { - // (+) icon at end of column header (to add a new column) - // opens up a pop up window - // - cy.get(".new-column-header").click(); - - // Redundant to feed column name. as alias is displayed & referred for - cy.get(".nc-column-name-input input").clear().type(childCol); - - // Column data type: to be set to lookup in this context - cy.get(".nc-ui-dt-dropdown").click(); - cy.getActiveMenu().contains("Lookup").click(); - - // Configure Child table & column names - fetchParentFromLabel("Child Table"); - cy.getActiveMenu().contains(childTable).click(); - - fetchParentFromLabel("Child column"); - cy.getActiveMenu().contains(childCol).click(); - - // click on Save - cy.get(".nc-col-create-or-edit-card").contains("Save").click(); - - // Verify if column exists. - // - cy.get(`th:contains(${childCol})`).should("exist"); - }; - - // routine to delete column - // - const deleteColumnByName = (childCol) => { - // verify if column exists before delete - cy.get(`th:contains(${childCol})`).should("exist"); - - // delete opiton visible on mouse-over - cy.get(`th:contains(${childCol}) .mdi-menu-down`) - .trigger("mouseover") - .click(); - - // delete/ confirm on pop-up - cy.get(".nc-column-delete").click(); - cy.getActiveModal().find("button:contains(Confirm)").click(); - - // validate if deleted (column shouldnt exist) - cy.get(`th:contains(${childCol})`).should("not.exist"); - }; - - /////////////////////////////////////////////////// - // Test case - - it("Add Lookup column (Address, PostalCode) & Delete", () => { - addLookUpColumn("Address", "PostalCode"); - - // Verify first entry, will be displayed as alias here 'childColumn (from childTable)' - cy.get(`tbody > :nth-child(1) > [data-col="PostalCode"]`) - .contains("4166") - .should("exist"); - - deleteColumnByName("PostalCode"); - }); - - it.skip("Add Lookup column (Country, CountryId) & Delete", () => { - addLookUpColumn("Country", "CountryId"); - - // Verify first entry, will be displayed as alias here 'childColumn (from childTable)' - cy.get(`tbody > :nth-child(1) > [data-col="CountryId"]`) - .contains("87") - .should("exist"); - - deleteColumnByName("CountryId"); - }); - }); }; // genTest('rest', false) diff --git a/scripts/cypress/integration/common/3d_rollup_column.js b/scripts/cypress/integration/common/3d_rollup_column.js index 2ace75741d..4db7e6e6ac 100644 --- a/scripts/cypress/integration/common/3d_rollup_column.js +++ b/scripts/cypress/integration/common/3d_rollup_column.js @@ -55,6 +55,8 @@ export const genTest = (apiType, dbType) => { fetchParentFromLabel("Aggregate function"); cy.getActiveMenu().contains(aggregateFunc).click(); + cy.snipActiveMenu("RollUp"); + // click on Save cy.get(".nc-col-create-or-edit-card").contains("Save").click(); diff --git a/scripts/cypress/integration/common/4a_table_view_grid_gallery_form.js b/scripts/cypress/integration/common/4a_table_view_grid_gallery_form.js index 56a6066714..49e99b510a 100644 --- a/scripts/cypress/integration/common/4a_table_view_grid_gallery_form.js +++ b/scripts/cypress/integration/common/4a_table_view_grid_gallery_form.js @@ -1,76 +1,81 @@ import { isTestSuiteActive } from "../../support/page_objects/projectConstants"; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; + if (!isTestSuiteActive(apiType, dbType)) return; - describe(`${apiType.toUpperCase()} api - Table views: Create/Edit/Delete`, () => { - const name = "Test" + Date.now(); + describe(`${apiType.toUpperCase()} api - Table views: Create/Edit/Delete`, () => { + const name = "Test" + Date.now(); - // Run once before test- create project (rest/graphql) - // - before(() => { - // open a table to work on views - // - cy.openTableTab("Country", 25); - }); + // Run once before test- create project (rest/graphql) + // + before(() => { + // open a table to work on views + // + cy.openTableTab("Country", 25); + }); - after(() => { - cy.closeTableTab("Country"); - }); + after(() => { + cy.closeTableTab("Country"); + }); + + // Common routine to create/edit/delete GRID & GALLERY view + // Input: viewType - 'grid'/'gallery' + // + const viewTest = (viewType) => { + it(`Create ${viewType} view`, () => { + // click on 'Grid/Gallery' button on Views bar + cy.get(`.nc-create-${viewType}-view`).click(); + + // Pop up window, click Submit (accepting default name for view) + cy.getActiveModal().find("button:contains(Submit)").click(); + cy.toastWait("View created successfully"); + + // validate if view was creted && contains default name 'Country1' + cy.get(`.nc-view-item.nc-${viewType}-view-item`) + .contains("Country1") + .should("exist"); + + cy.snip(`View_${viewType}`); + }); + + it(`Edit ${viewType} view name`, () => { + // click on edit-icon (becomes visible on hovering mouse) + cy.get(".nc-view-edit-icon").click({ + force: true, + timeout: 1000, + }); - // Common routine to create/edit/delete GRID & GALLERY view - // Input: viewType - 'grid'/'gallery' - // - const viewTest = (viewType) => { - it(`Create ${viewType} view`, () => { - // click on 'Grid/Gallery' button on Views bar - cy.get(`.nc-create-${viewType}-view`).click(); - - // Pop up window, click Submit (accepting default name for view) - cy.getActiveModal().find("button:contains(Submit)").click(); - cy.toastWait("View created successfully"); - - // validate if view was creted && contains default name 'Country1' - cy.get(`.nc-view-item.nc-${viewType}-view-item`) - .contains("Country1") - .should("exist"); - }); - - it(`Edit ${viewType} view name`, () => { - // click on edit-icon (becomes visible on hovering mouse) - cy.get(".nc-view-edit-icon").click({ force: true, timeout: 1000 }); - - // feed new name - cy.get(`.nc-${viewType}-view-item input`).type( - `${viewType}View-1{enter}` - ); - cy.toastWait("View renamed successfully"); - - // validate - cy.get(`.nc-view-item.nc-${viewType}-view-item`) - .contains(`${viewType}View-1`) - .should("exist"); - }); - - it(`Delete ${viewType} view`, () => { - // number of view entries should be 2 before we delete - cy.get(".nc-view-item").its("length").should("eq", 2); - - // click on delete icon (becomes visible on hovering mouse) - cy.get(".nc-view-delete-icon").click({ force: true }); - cy.toastWait("View deleted successfully"); - - // confirm if the number of veiw entries is reduced by 1 - cy.get(".nc-view-item").its("length").should("eq", 1); - }); - }; - - // below four scenario's will be invoked twice, once for rest & then for graphql - viewTest("grid"); - viewTest("gallery"); - viewTest("form"); - // viewTest("kanban"); - }); + // feed new name + cy.get(`.nc-${viewType}-view-item input`).type( + `${viewType}View-1{enter}` + ); + cy.toastWait("View renamed successfully"); + + // validate + cy.get(`.nc-view-item.nc-${viewType}-view-item`) + .contains(`${viewType}View-1`) + .should("exist"); + }); + + it(`Delete ${viewType} view`, () => { + // number of view entries should be 2 before we delete + cy.get(".nc-view-item").its("length").should("eq", 2); + + // click on delete icon (becomes visible on hovering mouse) + cy.get(".nc-view-delete-icon").click({ force: true }); + cy.toastWait("View deleted successfully"); + + // confirm if the number of veiw entries is reduced by 1 + cy.get(".nc-view-item").its("length").should("eq", 1); + }); + }; + + // below four scenario's will be invoked twice, once for rest & then for graphql + viewTest("grid"); + viewTest("gallery"); + viewTest("form"); + // viewTest("kanban"); + }); }; /** diff --git a/scripts/cypress/integration/common/4b_table_view_share.js b/scripts/cypress/integration/common/4b_table_view_share.js index 6fc2b8c7cf..e69b7bbcf1 100644 --- a/scripts/cypress/integration/common/4b_table_view_share.js +++ b/scripts/cypress/integration/common/4b_table_view_share.js @@ -10,12 +10,17 @@ const generateLinkWithPwd = () => { // .contains("Share View") // .click(); mainPage.shareView().click(); + + cy.snipActiveModal("Modal_ShareView") // enable checkbox & feed pwd, save cy.getActiveModal() .find('[role="switch"][type="checkbox"]') .click({ force: true }); cy.getActiveModal().find('input[type="password"]').type("1"); + + cy.snipActiveModal("Modal_ShareView_Password"); + cy.getActiveModal().find('button:contains("Save password")').click(); cy.toastWait("Successfully updated"); diff --git a/scripts/cypress/integration/common/4d_table_view_grid_locked.js b/scripts/cypress/integration/common/4d_table_view_grid_locked.js index 254d205d7b..ccd14a3d2e 100644 --- a/scripts/cypress/integration/common/4d_table_view_grid_locked.js +++ b/scripts/cypress/integration/common/4d_table_view_grid_locked.js @@ -25,6 +25,7 @@ export const genTest = (apiType, dbType) => { // on menu, collaboration view appears first (at index 0) // followed by Locked view (at index 1) cy.get(".xc-toolbar").find(".nc-view-lock-menu:enabled").click(); + cy.snipActiveMenu("Menu_Collaboration") cy.getActiveMenu().find('[role="menuitem"]').eq(menuOption).click(); // expected toolbar for Lock view: Only lock-view menu, reload, toggle-nav-drawer to be enabled diff --git a/scripts/cypress/integration/common/4e_form_view_share.js b/scripts/cypress/integration/common/4e_form_view_share.js index 5ae04a5915..ec765b4054 100644 --- a/scripts/cypress/integration/common/4e_form_view_share.js +++ b/scripts/cypress/integration/common/4e_form_view_share.js @@ -4,193 +4,222 @@ import { mainPage } from "../../support/page_objects/mainPage"; let storedURL = ""; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; + if (!isTestSuiteActive(apiType, dbType)) return; - describe(`${apiType.toUpperCase()} api - FORM view (Share)`, () => { - const name = "Test" + Date.now(); + describe(`${apiType.toUpperCase()} api - FORM view (Share)`, () => { + const name = "Test" + Date.now(); - // Run once before test- create project (rest/graphql) - // - before(() => { - // open a table to work on views - // - cy.openTableTab("City", 25); - }); - - beforeEach(() => { - cy.restoreLocalStorage(); - }); + // Run once before test- create project (rest/graphql) + // + before(() => { + // open a table to work on views + // + cy.openTableTab("City", 25); + }); - afterEach(() => { - cy.saveLocalStorage(); - }); + beforeEach(() => { + cy.restoreLocalStorage(); + }); - after(() => { - cy.closeTableTab("City"); - }); + afterEach(() => { + cy.saveLocalStorage(); + }); - // Common routine to create/edit/delete GRID & GALLERY view - // Input: viewType - 'grid'/'gallery' - // - const viewTest = (viewType) => { - it(`Create ${viewType} view`, () => { - // click on 'Grid/Gallery' button on Views bar - cy.get(`.nc-create-${viewType}-view`).click(); - - // Pop up window, click Submit (accepting default name for view) - cy.getActiveModal().find("button:contains(Submit)").click(); - - cy.toastWait("View created successfully"); - - // Prepare form - // add header, description - // add post submission message - // swap position for City, LastUpdate fields - // remove City=>Address field - cy.get(".nc-form > .mx-auto").find('[type="checkbox"]').eq(1).click(); - cy.get(".nc-form > .mx-auto") - .find('[type="checkbox"]') - .eq(1) - .should("be.checked"); - - cy.get(".nc-form").find('[placeholder="Form Title"]').type("A B C D"); - cy.get(".nc-form") - .find('[placeholder="Add form description"]') - .type("Some description about form comes here"); - cy.get(".nc-form > .mx-auto").find("textarea").type("Congratulations!"); - - cy.get("#data-table-form-City").drag("#data-table-form-LastUpdate"); - cy.get('[title="City => Address"]').drag(".nc-drag-n-drop-to-hide"); - - cy.get(".nc-form > .mx-auto") - .find('[type="checkbox"]') - .eq(1) - .should("be.checked"); - - // store base URL- to re-visit and delete form view later - cy.url().then((url) => { - storedURL = url; + after(() => { + cy.closeTableTab("City"); }); - }); - - it(`Share form view`, () => { - cy.get(".nc-form > .mx-auto") - .find('[type="checkbox"]') - .eq(1) - .should("be.checked"); - cy.get(`.nc-view-item.nc-${viewType}-view-item`) - .contains("City1") - .click(); - // cy.get(".v-navigation-drawer__content > .container") - // .find(".v-list > .v-list-item") - // .contains("Share View") - // .click(); - mainPage.shareView().click(); - - // copy link text, visit URL - cy.getActiveModal() - .find(".share-link-box") - .contains("/nc/form/", { timeout: 10000 }) - .then(($obj) => { - let linkText = $obj.text().trim(); - cy.log(linkText); - cy.visit(linkText, { - baseUrl: null, + + // Common routine to create/edit/delete GRID & GALLERY view + // Input: viewType - 'grid'/'gallery' + // + const viewTest = (viewType) => { + it(`Create ${viewType} view`, () => { + // click on 'Grid/Gallery' button on Views bar + cy.get(`.nc-create-${viewType}-view`).click(); + + // Pop up window, click Submit (accepting default name for view) + cy.getActiveModal().find("button:contains(Submit)").click(); + + cy.toastWait("View created successfully"); + + // Prepare form + // add header, description + // add post submission message + // swap position for City, LastUpdate fields + // remove City=>Address field + cy.get(".nc-form > .mx-auto") + .find('[type="checkbox"]') + .eq(1) + .click(); + cy.get(".nc-form > .mx-auto") + .find('[type="checkbox"]') + .eq(1) + .should("be.checked"); + + cy.get(".nc-form") + .find('[placeholder="Form Title"]') + .type("A B C D"); + cy.get(".nc-form") + .find('[placeholder="Add form description"]') + .type("Some description about form comes here"); + cy.get(".nc-form > .mx-auto") + .find("textarea") + .type("Congratulations!"); + + cy.get("#data-table-form-City").drag( + "#data-table-form-LastUpdate" + ); + cy.get('[title="City => Address"]').drag( + ".nc-drag-n-drop-to-hide" + ); + + cy.get(".nc-form > .mx-auto") + .find('[type="checkbox"]') + .eq(1) + .should("be.checked"); + + // store base URL- to re-visit and delete form view later + cy.url().then((url) => { + storedURL = url; + }); }); - // wait for share view page to load! - cy.get(".nc-form").should("exist"); - - // New form appeared? Header & description should exist - cy.get(".nc-form", { timeout: 10000 }) - .find("h2") - .contains("A B C D") - .should("exist"); - cy.get(".nc-form", { timeout: 10000 }) - .find(".body-1") - .contains("Some description about form comes here") - .should("exist"); - - // all fields, barring removed field should exist - cy.get('[title="City"]').should("exist"); - cy.get('[title="LastUpdate"]').should("exist"); - cy.get('[title="Country <= City"]').should("exist"); - cy.get('[title="City => Address"]').should("not.exist"); - - // order of LastUpdate & City field is retained - cy.get(".nc-field-wrapper") - .eq(0) - .contains("LastUpdate") - .should("exist"); - cy.get(".nc-field-wrapper").eq(1).contains("City").should("exist"); - - // submit form, to read message - cy.get("#data-table-form-City").type("_abc"); - cy.get("#data-table-form-LastUpdate").click(); - cy.getActiveModal().find("button").contains("19").click(); - cy.getActiveModal().find("button").contains("OK").click(); - cy.get("button").contains("Link to 'Country'").click(); - cy.getActiveModal() - .find(".child-card") - .contains("Afghanistan") - .click(); - - // submit button & validate - cy.get(".nc-form").find("button").contains("Submit").click(); - cy.toastWait("Congratulations"); - cy.get(".v-alert") - .contains("Congratulations") - .should("exist") - .then(() => { - cy.get(".nc-form").should("exist"); - - // validate if form has appeared again - cy.get(".nc-form", { timeout: 10000 }) - .find("h2") - .contains("A B C D") - .should("exist"); - cy.get(".nc-form", { timeout: 10000 }) - .find(".body-1") - .contains("Some description about form comes here") - .should("exist"); - }); - }); - }); - - it(`Delete ${viewType} view`, () => { - // go back to base page - cy.visit(storedURL, { - baseUrl: null, - }); + it(`Share form view`, () => { + cy.get(".nc-form > .mx-auto") + .find('[type="checkbox"]') + .eq(1) + .should("be.checked"); + cy.get(`.nc-view-item.nc-${viewType}-view-item`) + .contains("City1") + .click(); + // cy.get(".v-navigation-drawer__content > .container") + // .find(".v-list > .v-list-item") + // .contains("Share View") + // .click(); + mainPage.shareView().click(); + + cy.snipActiveModal("Modal_ShareView"); + + // copy link text, visit URL + cy.getActiveModal() + .find(".share-link-box") + .contains("/nc/form/", { timeout: 10000 }) + .then(($obj) => { + let linkText = $obj.text().trim(); + cy.log(linkText); + cy.visit(linkText, { + baseUrl: null, + }); + + // wait for share view page to load! + cy.get(".nc-form").should("exist"); + + cy.snip("ShareView_Form"); + + // New form appeared? Header & description should exist + cy.get(".nc-form", { timeout: 10000 }) + .find("h2") + .contains("A B C D") + .should("exist"); + cy.get(".nc-form", { timeout: 10000 }) + .find(".body-1") + .contains("Some description about form comes here") + .should("exist"); + + // all fields, barring removed field should exist + cy.get('[title="City"]').should("exist"); + cy.get('[title="LastUpdate"]').should("exist"); + cy.get('[title="Country <= City"]').should("exist"); + cy.get('[title="City => Address"]').should("not.exist"); + + // order of LastUpdate & City field is retained + cy.get(".nc-field-wrapper") + .eq(0) + .contains("LastUpdate") + .should("exist"); + cy.get(".nc-field-wrapper") + .eq(1) + .contains("City") + .should("exist"); + + // submit form, to read message + cy.get("#data-table-form-City").type("_abc"); + cy.get("#data-table-form-LastUpdate").click(); + cy.getActiveModal() + .find("button") + .contains("19") + .click(); + cy.getActiveModal() + .find("button") + .contains("OK") + .click(); + cy.get("button").contains("Link to 'Country'").click(); + cy.getActiveModal() + .find(".child-card") + .contains("Afghanistan") + .click(); + + // submit button & validate + cy.get(".nc-form") + .find("button") + .contains("Submit") + .click(); + cy.toastWait("Congratulations"); + cy.get(".v-alert") + .contains("Congratulations") + .should("exist") + .then(() => { + cy.get(".nc-form").should("exist"); + + // validate if form has appeared again + cy.get(".nc-form", { timeout: 10000 }) + .find("h2") + .contains("A B C D") + .should("exist"); + cy.get(".nc-form", { timeout: 10000 }) + .find(".body-1") + .contains( + "Some description about form comes here" + ) + .should("exist"); + }); + }); + }); - // number of view entries should be 2 before we delete - cy.get(".nc-view-item").its("length").should("eq", 2); - - // click on delete icon (becomes visible on hovering mouse) - cy.get(".nc-view-delete-icon").click({ force: true }); - cy.toastWait("View deleted successfully"); - - // confirm if the number of veiw entries is reduced by 1 - cy.get(".nc-view-item").its("length").should("eq", 1); - - // clean up newly added rows into Country table operations - // this auto verifies successfull addition of rows to table as well - mainPage.getPagination(25).click(); - cy.get(".nc-grid-row").should("have.length", 1); - mainPage - .getRow(1) - .find(".mdi-checkbox-blank-outline") - .click({ force: true }); - - mainPage.getCell("City", 1).rightclick(); - cy.getActiveMenu().contains("Delete Selected Row").click(); - // cy.toastWait('Deleted selected rows successfully') - }); - }; - - // below scenario's will be invoked twice, once for rest & then for graphql - viewTest("form"); - }); + it(`Delete ${viewType} view`, () => { + // go back to base page + cy.visit(storedURL, { + baseUrl: null, + }); + + // number of view entries should be 2 before we delete + cy.get(".nc-view-item").its("length").should("eq", 2); + + // click on delete icon (becomes visible on hovering mouse) + cy.get(".nc-view-delete-icon").click({ force: true }); + cy.toastWait("View deleted successfully"); + + // confirm if the number of veiw entries is reduced by 1 + cy.get(".nc-view-item").its("length").should("eq", 1); + + // clean up newly added rows into Country table operations + // this auto verifies successfull addition of rows to table as well + mainPage.getPagination(25).click(); + cy.get(".nc-grid-row").should("have.length", 1); + mainPage + .getRow(1) + .find(".mdi-checkbox-blank-outline") + .click({ force: true }); + + mainPage.getCell("City", 1).rightclick(); + cy.getActiveMenu().contains("Delete Selected Row").click(); + // cy.toastWait('Deleted selected rows successfully') + }); + }; + + // below scenario's will be invoked twice, once for rest & then for graphql + viewTest("form"); + }); }; /** diff --git a/scripts/cypress/integration/common/4f_grid_view_share.js b/scripts/cypress/integration/common/4f_grid_view_share.js index 9751c4bb45..bbc033d1b4 100644 --- a/scripts/cypress/integration/common/4f_grid_view_share.js +++ b/scripts/cypress/integration/common/4f_grid_view_share.js @@ -12,418 +12,443 @@ let storedURL = ""; let viewURL = {}; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; - - const generateViewLink = (viewName) => { - // click on share view - // cy.get(".v-navigation-drawer__content > .container") - // .find(".v-list > .v-list-item") - // .contains("Share View") - // .click(); - mainPage.shareView().click(); - - // wait, as URL initially will be /undefined - cy.getActiveModal() - .find(".share-link-box") - .contains("/nc/view/", { timeout: 10000 }) - .should("exist"); - - // copy link text, visit URL - cy.getActiveModal() - .find(".share-link-box") - .contains("/nc/view/", { timeout: 10000 }) - .then(($obj) => { - cy.get("body").type("{esc}"); - // viewURL.push($obj.text()) - viewURL[viewName] = $obj.text().trim(); - }); - }; - - describe(`${apiType.toUpperCase()} api - GRID view (Share)`, () => { - // Run once before test- create project (rest/graphql) - // - before(() => { - // open a table to work on views - // - cy.openTableTab("Address", 25); - - cy.saveLocalStorage(); - }); - - beforeEach(() => { - cy.restoreLocalStorage(); - }); - - afterEach(() => { - cy.saveLocalStorage(); - }); - - after(() => { - // close table - // mainPage.deleteCreatedViews() - cy.closeTableTab("Address"); - }); + if (!isTestSuiteActive(apiType, dbType)) return; - // Common routine to create/edit/delete GRID & GALLERY view - // Input: viewType - 'grid'/'gallery' - // - const viewTest = (viewType) => { - it(`Create ${viewType.toUpperCase()} view`, () => { - // create a normal public view - cy.get(`.nc-create-${viewType}-view`).click(); - cy.getActiveModal().find("button:contains(Submit)").click(); - cy.toastWait("View created successfully"); - - // store base URL- to re-visit and delete form view later - cy.url().then((url) => { - storedURL = url; - }); - }); - - it(`Share ${viewType.toUpperCase()} hide, sort, filter & verify`, () => { - cy.get(`.nc-view-item.nc-${viewType}-view-item`) - .contains("Address1") - .click(); - mainPage.hideField("Address2"); - mainPage.sortField("District", "Z -> A"); - mainPage.filterField("Address", "is like", "Ab"); - generateViewLink("combined"); - cy.log(viewURL["combined"]); - }); - - it(`Share GRID view : ensure we have only one link even if shared multiple times`, () => { - // generate view link multiple times - generateViewLink("combined"); - generateViewLink("combined"); - - // verify if only one link exists in table + const generateViewLink = (viewName) => { + // click on share view // cy.get(".v-navigation-drawer__content > .container") // .find(".v-list > .v-list-item") // .contains("Share View") - // .parent() - // .find("button.mdi-dots-vertical") // .click(); - mainPage.shareViewList().click(); - - // cy.getActiveMenu().find(".v-list-item").contains("Views List").click(); - - cy.get('th:contains("View Link")').should("exist"); - - cy.get('th:contains("View Link")') - .parent() - .parent() - .next() - .find("tr") - .its("length") - .should("eq", 1) - .then(() => { - // cy.get(".v-overlay__content > .d-flex > .v-icon").click(); - // close modal (fix me! add a close button to share view list modal) - cy.get('.v-overlay--active > .v-overlay__scrim').click({force: true}); - }); - }); - - it(`Share ${viewType.toUpperCase()} view : Visit URL, Verify title`, () => { - // visit public view - cy.visit(viewURL["combined"], { - baseUrl: null, - }); - - // wait for page rendering to complete - cy.get(".nc-grid-row").should("have.length", 18); - - // verify title - cy.get("div.model-name").contains("Address1").should("exist"); - }); - - it(`Share ${viewType.toUpperCase()} view : verify fields hidden/open`, () => { - // verify column headers - cy.get('[data-col="Address"]').should("exist"); - cy.get('[data-col="Address2"]').should("not.exist"); - cy.get('[data-col="District"]').should("exist"); - }); - - it(`Share ${viewType.toUpperCase()} view : verify fields sort/ filter`, () => { - // country column content verification before sort - mainPage - .getCell("District", 1) - .contains("West Bengali") - .should("exist"); - mainPage.getCell("District", 2).contains("Tutuila").should("exist"); - mainPage.getCell("District", 3).contains("Tamil Nadu").should("exist"); - }); - - it(`Share ${viewType.toUpperCase()} view : verify download CSV`, () => { - mainPage.hideField("LastUpdate"); - const verifyCsv = (retrievedRecords) => { - // expected output, statically configured - let storedRecords = [ - `Address,District,PostalCode,Phone,Location,Address => Customer,Address => Staff,City <= Address,Address <=> Staff`, - `1013 Tabuk Boulevard,West Bengali,96203,158399646978,[object Object],2,,Kanchrapara,`, - `1892 Nabereznyje Telny Lane,Tutuila,28396,478229987054,[object Object],2,,Tafuna,`, - `1993 Tabuk Lane,Tamil Nadu,64221,648482415405,[object Object],2,,Tambaram,`, - `1661 Abha Drive,Tamil Nadu,14400,270456873752,[object Object],1,,Pudukkottai,`, - ]; - - for (let i = 0; i < storedRecords.length; i++) { - let strCol = storedRecords[i].split(","); - let retCol = retrievedRecords[i].split(","); - for (let j = 0; j < 4; j++) { - expect(strCol[j]).to.be.equal(retCol[j]); - } - // expect(retrievedRecords[i]).to.be.equal(storedRecords[i]) - } - }; + mainPage.shareView().click(); - // download & verify - mainPage.downloadAndVerifyCsv(`Address_exported_1.csv`, verifyCsv); - mainPage.unhideField("LastUpdate"); - }); - - it(`Share ${viewType.toUpperCase()} view : Disable sort`, () => { - // remove sort and validate - mainPage.clearSort(); - mainPage - .getCell("District", 1) - .contains("Southern Mindanao") - .should("exist"); - }); - - it(`Share ${viewType.toUpperCase()} view : Enable sort`, () => { - // Sort menu operations (Country Column, Z->A) - mainPage.sortField("District", "Z -> A"); - mainPage - .getCell("District", 1) - .contains("West Bengali") - .should("exist"); - }); - - it(`Share ${viewType.toUpperCase()} view : Create Filter`, () => { - // add filter & validate - mainPage.filterField("District", "is like", "Tamil"); - // wait for page rendering to complete - cy.get(".nc-grid-row").should("have.length", 2); - mainPage.getCell("District", 1).contains("Tamil").should("exist"); - }); - - it(`Share ${viewType.toUpperCase()} view : verify download CSV after local filter`, () => { - mainPage.hideField("LastUpdate"); - const verifyCsv = (retrievedRecords) => { - // expected output, statically configured - let storedRecords = [ - `Address,District,PostalCode,Phone,Location,Address => Customer,Address => Staff,City <= Address,Address <=> Staff`, - `1993 Tabuk Lane,Tamil Nadu,64221,648482415405,[object Object],2,,Tambaram,`, - `1661 Abha Drive,Tamil Nadu,14400,270456873752,[object Object],1,,Pudukkottai,`, - ]; - - // for (let i = 0; i < storedRecords.length; i++) { - // expect(retrievedRecords[i]).to.be.equal(storedRecords[i]) - // } - - for (let i = 0; i < storedRecords.length; i++) { - let strCol = storedRecords[i].split(","); - let retCol = retrievedRecords[i].split(","); - for (let j = 0; j < 4; j++) { - expect(strCol[j]).to.be.equal(retCol[j]); - } - } - }; - mainPage.downloadAndVerifyCsv(`Address_exported_1.csv`, verifyCsv); - mainPage.unhideField("LastUpdate"); - }); - - it(`Share ${viewType.toUpperCase()} view : Delete Filter`, () => { - // Remove sort and Validate - mainPage.filterReset(); - mainPage - .getCell("District", 1) - .contains("West Bengali") - .should("exist"); - }); - - it(`Share GRID view : Virtual column validation > has many`, () => { - // verify column headers - cy.get('[data-col="Address => Customer"]').should("exist"); - cy.get('[data-col="Address => Staff"]').should("exist"); - cy.get('[data-col="City <= Address"]').should("exist"); - cy.get('[data-col="Address <=> Staff"]').should("exist"); - - // has many field validation - mainPage - .getCell("Address => Customer", 3) - .click() - .find("button.mdi-close-thick") - .should("not.exist"); - mainPage - .getCell("Address => Customer", 3) - .click() - .find("button.mdi-plus") - .should("not.exist"); - mainPage - .getCell("Address => Customer", 3) - .click() - .find("button.mdi-arrow-expand") - .click(); - - cy.getActiveModal().find("button.mdi-reload").should("exist"); + // wait, as URL initially will be /undefined cy.getActiveModal() - .find("button") - .contains("Link to") - .should("not.exist"); - cy.getActiveModal().find(".child-card").contains("2").should("exist"); - cy.getActiveModal() - .find(".child-card") - .find("button") - .should("not.exist"); - cy.get("body").type("{esc}"); - }); - - it(`Share GRID view : Virtual column validation > belongs to`, () => { - // belongs to field validation - mainPage - .getCell("City <= Address", 1) - .click() - .find("button.mdi-close-thick") - .should("not.exist"); - mainPage - .getCell("City <= Address", 1) - .click() - .find("button.mdi-arrow-expand") - .should("not.exist"); - mainPage - .getCell("City <= Address", 1) - .find(".v-chip") - .contains("Kanchrapara") - .should("exist"); - }); - - it(`Share GRID view : Virtual column validation > many to many`, () => { - // many-to-many field validation - mainPage - .getCell("Address <=> Staff", 1) - .click() - .find("button.mdi-close-thick") - .should("not.exist"); - mainPage - .getCell("Address <=> Staff", 1) - .click() - .find("button.mdi-plus") - .should("not.exist"); - mainPage - .getCell("Address <=> Staff", 1) - .click() - .find("button.mdi-arrow-expand") - .click(); - - cy.getActiveModal().find("button.mdi-reload").should("exist"); + .find(".share-link-box") + .contains("/nc/view/", { timeout: 10000 }) + .should("exist"); + + // copy link text, visit URL cy.getActiveModal() - .find("button") - .contains("Link to") - .should("not.exist"); - cy.get("body").type("{esc}"); - }); - - it(`Delete ${viewType.toUpperCase()} view`, () => { - // go back to base page - cy.visit(storedURL, { - baseUrl: null, + .find(".share-link-box") + .contains("/nc/view/", { timeout: 10000 }) + .then(($obj) => { + cy.get("body").type("{esc}"); + // viewURL.push($obj.text()) + viewURL[viewName] = $obj.text().trim(); + }); + }; + + describe(`${apiType.toUpperCase()} api - GRID view (Share)`, () => { + // Run once before test- create project (rest/graphql) + // + before(() => { + // open a table to work on views + // + cy.openTableTab("Address", 25); + + cy.saveLocalStorage(); }); - // number of view entries should be 2 before we delete - cy.get(".nc-view-item").its("length").should("eq", 2); + beforeEach(() => { + cy.restoreLocalStorage(); + }); - cy.get(".nc-view-delete-icon").eq(0).click({ force: true }); - cy.toastWait("View deleted successfully"); + afterEach(() => { + cy.saveLocalStorage(); + }); - // confirm if the number of veiw entries is reduced by 1 - cy.get(".nc-view-item").its("length").should("eq", 1); - }); - }; + after(() => { + // close table + // mainPage.deleteCreatedViews() + cy.closeTableTab("Address"); + }); - // below scenario's will be invoked twice, once for rest & then for graphql - viewTest("grid"); - }); - - describe(`${apiType.toUpperCase()} api - Grid view/ row-column update verification`, () => { - before(() => { - // Address table has belongs to, has many & many-to-many - cy.openTableTab("Country", 25); - - cy.saveLocalStorage(); - // store base URL- to re-visit and delete form view later - cy.url().then((url) => { - storedURL = url; - generateViewLink("rowColUpdate"); - }); - }); + // Common routine to create/edit/delete GRID & GALLERY view + // Input: viewType - 'grid'/'gallery' + // + const viewTest = (viewType) => { + it(`Create ${viewType.toUpperCase()} view`, () => { + // create a normal public view + cy.get(`.nc-create-${viewType}-view`).click(); + cy.getActiveModal().find("button:contains(Submit)").click(); + cy.toastWait("View created successfully"); + + // store base URL- to re-visit and delete form view later + cy.url().then((url) => { + storedURL = url; + }); + }); + + it(`Share ${viewType.toUpperCase()} hide, sort, filter & verify`, () => { + cy.get(`.nc-view-item.nc-${viewType}-view-item`) + .contains("Address1") + .click(); + mainPage.hideField("Address2"); + mainPage.sortField("District", "Z -> A"); + mainPage.filterField("Address", "is like", "Ab"); + generateViewLink("combined"); + cy.log(viewURL["combined"]); + }); + + it(`Share GRID view : ensure we have only one link even if shared multiple times`, () => { + // generate view link multiple times + generateViewLink("combined"); + generateViewLink("combined"); + + // verify if only one link exists in table + // cy.get(".v-navigation-drawer__content > .container") + // .find(".v-list > .v-list-item") + // .contains("Share View") + // .parent() + // .find("button.mdi-dots-vertical") + // .click(); + mainPage.shareViewList().click(); + + // cy.getActiveMenu().find(".v-list-item").contains("Views List").click(); + + cy.get('th:contains("View Link")').should("exist"); + + cy.get('th:contains("View Link")') + .parent() + .parent() + .next() + .find("tr") + .its("length") + .should("eq", 1) + .then(() => { + // cy.get(".v-overlay__content > .d-flex > .v-icon").click(); + // close modal (fix me! add a close button to share view list modal) + cy.get(".v-overlay--active > .v-overlay__scrim").click({ + force: true, + }); + }); + }); + + it(`Share ${viewType.toUpperCase()} view : Visit URL, Verify title`, () => { + // visit public view + cy.visit(viewURL["combined"], { + baseUrl: null, + }); + + // wait for page rendering to complete + cy.get(".nc-grid-row").should("have.length", 18); + + cy.snip("ShareView_Grid"); + + // verify title + cy.get("div.model-name").contains("Address1").should("exist"); + }); + + it(`Share ${viewType.toUpperCase()} view : verify fields hidden/open`, () => { + // verify column headers + cy.get('[data-col="Address"]').should("exist"); + cy.get('[data-col="Address2"]').should("not.exist"); + cy.get('[data-col="District"]').should("exist"); + }); + + it(`Share ${viewType.toUpperCase()} view : verify fields sort/ filter`, () => { + // country column content verification before sort + mainPage + .getCell("District", 1) + .contains("West Bengali") + .should("exist"); + mainPage + .getCell("District", 2) + .contains("Tutuila") + .should("exist"); + mainPage + .getCell("District", 3) + .contains("Tamil Nadu") + .should("exist"); + }); + + it(`Share ${viewType.toUpperCase()} view : verify download CSV`, () => { + mainPage.hideField("LastUpdate"); + const verifyCsv = (retrievedRecords) => { + // expected output, statically configured + let storedRecords = [ + `Address,District,PostalCode,Phone,Location,Address => Customer,Address => Staff,City <= Address,Address <=> Staff`, + `1013 Tabuk Boulevard,West Bengali,96203,158399646978,[object Object],2,,Kanchrapara,`, + `1892 Nabereznyje Telny Lane,Tutuila,28396,478229987054,[object Object],2,,Tafuna,`, + `1993 Tabuk Lane,Tamil Nadu,64221,648482415405,[object Object],2,,Tambaram,`, + `1661 Abha Drive,Tamil Nadu,14400,270456873752,[object Object],1,,Pudukkottai,`, + ]; + + for (let i = 0; i < storedRecords.length; i++) { + let strCol = storedRecords[i].split(","); + let retCol = retrievedRecords[i].split(","); + for (let j = 0; j < 4; j++) { + expect(strCol[j]).to.be.equal(retCol[j]); + } + // expect(retrievedRecords[i]).to.be.equal(storedRecords[i]) + } + }; + + // download & verify + mainPage.downloadAndVerifyCsv( + `Address_exported_1.csv`, + verifyCsv + ); + mainPage.unhideField("LastUpdate"); + }); + + it(`Share ${viewType.toUpperCase()} view : Disable sort`, () => { + // remove sort and validate + mainPage.clearSort(); + mainPage + .getCell("District", 1) + .contains("Southern Mindanao") + .should("exist"); + }); + + it(`Share ${viewType.toUpperCase()} view : Enable sort`, () => { + // Sort menu operations (Country Column, Z->A) + mainPage.sortField("District", "Z -> A"); + mainPage + .getCell("District", 1) + .contains("West Bengali") + .should("exist"); + }); + + it(`Share ${viewType.toUpperCase()} view : Create Filter`, () => { + // add filter & validate + mainPage.filterField("District", "is like", "Tamil"); + // wait for page rendering to complete + cy.get(".nc-grid-row").should("have.length", 2); + mainPage + .getCell("District", 1) + .contains("Tamil") + .should("exist"); + }); + + it(`Share ${viewType.toUpperCase()} view : verify download CSV after local filter`, () => { + mainPage.hideField("LastUpdate"); + const verifyCsv = (retrievedRecords) => { + // expected output, statically configured + let storedRecords = [ + `Address,District,PostalCode,Phone,Location,Address => Customer,Address => Staff,City <= Address,Address <=> Staff`, + `1993 Tabuk Lane,Tamil Nadu,64221,648482415405,[object Object],2,,Tambaram,`, + `1661 Abha Drive,Tamil Nadu,14400,270456873752,[object Object],1,,Pudukkottai,`, + ]; + + // for (let i = 0; i < storedRecords.length; i++) { + // expect(retrievedRecords[i]).to.be.equal(storedRecords[i]) + // } + + for (let i = 0; i < storedRecords.length; i++) { + let strCol = storedRecords[i].split(","); + let retCol = retrievedRecords[i].split(","); + for (let j = 0; j < 4; j++) { + expect(strCol[j]).to.be.equal(retCol[j]); + } + } + }; + mainPage.downloadAndVerifyCsv( + `Address_exported_1.csv`, + verifyCsv + ); + mainPage.unhideField("LastUpdate"); + }); + + it(`Share ${viewType.toUpperCase()} view : Delete Filter`, () => { + // Remove sort and Validate + mainPage.filterReset(); + mainPage + .getCell("District", 1) + .contains("West Bengali") + .should("exist"); + }); + + it(`Share GRID view : Virtual column validation > has many`, () => { + // verify column headers + cy.get('[data-col="Address => Customer"]').should("exist"); + cy.get('[data-col="Address => Staff"]').should("exist"); + cy.get('[data-col="City <= Address"]').should("exist"); + cy.get('[data-col="Address <=> Staff"]').should("exist"); + + // has many field validation + mainPage + .getCell("Address => Customer", 3) + .click() + .find("button.mdi-close-thick") + .should("not.exist"); + mainPage + .getCell("Address => Customer", 3) + .click() + .find("button.mdi-plus") + .should("not.exist"); + mainPage + .getCell("Address => Customer", 3) + .click() + .find("button.mdi-arrow-expand") + .click(); + + cy.getActiveModal().find("button.mdi-reload").should("exist"); + cy.getActiveModal() + .find("button") + .contains("Link to") + .should("not.exist"); + cy.getActiveModal() + .find(".child-card") + .contains("2") + .should("exist"); + cy.getActiveModal() + .find(".child-card") + .find("button") + .should("not.exist"); + cy.get("body").type("{esc}"); + }); + + it(`Share GRID view : Virtual column validation > belongs to`, () => { + // belongs to field validation + mainPage + .getCell("City <= Address", 1) + .click() + .find("button.mdi-close-thick") + .should("not.exist"); + mainPage + .getCell("City <= Address", 1) + .click() + .find("button.mdi-arrow-expand") + .should("not.exist"); + mainPage + .getCell("City <= Address", 1) + .find(".v-chip") + .contains("Kanchrapara") + .should("exist"); + }); + + it(`Share GRID view : Virtual column validation > many to many`, () => { + // many-to-many field validation + mainPage + .getCell("Address <=> Staff", 1) + .click() + .find("button.mdi-close-thick") + .should("not.exist"); + mainPage + .getCell("Address <=> Staff", 1) + .click() + .find("button.mdi-plus") + .should("not.exist"); + mainPage + .getCell("Address <=> Staff", 1) + .click() + .find("button.mdi-arrow-expand") + .click(); + + cy.getActiveModal().find("button.mdi-reload").should("exist"); + cy.getActiveModal() + .find("button") + .contains("Link to") + .should("not.exist"); + cy.get("body").type("{esc}"); + }); + + it(`Delete ${viewType.toUpperCase()} view`, () => { + // go back to base page + cy.visit(storedURL, { + baseUrl: null, + }); + + // number of view entries should be 2 before we delete + cy.get(".nc-view-item").its("length").should("eq", 2); + + cy.get(".nc-view-delete-icon").eq(0).click({ force: true }); + cy.toastWait("View deleted successfully"); + + // confirm if the number of veiw entries is reduced by 1 + cy.get(".nc-view-item").its("length").should("eq", 1); + }); + }; - after(() => { - // close table - cy.restoreLocalStorage(); - cy.visit(storedURL, { - baseUrl: null, - }); - - // delete row - mainPage.getPagination(5).click(); - // wait for page rendering to complete - cy.get(".nc-grid-row").should("have.length", 10); - mainPage - .getRow(10) - .find(".mdi-checkbox-blank-outline") - .click({ force: true }); - mainPage.getCell("Country", 10).rightclick(); - cy.getActiveMenu().contains("Delete Selected Row").click(); - - // delete column - cy.get(`th:contains('dummy') .mdi-menu-down`) - .trigger("mouseover") - .click(); - cy.get(".nc-column-delete").click(); - cy.get("button:contains(Confirm)").click(); - - cy.toastWait("Update table successful"); - - mainPage.deleteCreatedViews(); - - // close table - cy.closeTableTab("Country"); + // below scenario's will be invoked twice, once for rest & then for graphql + viewTest("grid"); }); - it(`Generate default Shared GRID view URL`, () => { - // add row - cy.get(".nc-add-new-row-btn").click({ force: true }); - cy.get("#data-table-form-Country > input").first().click().type("a"); - cy.contains("Save Row").filter("button").click({ force: true }); - cy.toastWait("updated successfully"); - - // add column - mainPage.addColumn("dummy", "Country"); - - // visit public view - cy.log(viewURL["rowColUpdate"]); - cy.restoreLocalStorage(); - cy.visit(viewURL["rowColUpdate"], { - baseUrl: null, - }); //5 - // wait for public view page to load! - // wait for page rendering to complete - cy.get(".nc-grid-row").should("have.length", 25); - }); + describe(`${apiType.toUpperCase()} api - Grid view/ row-column update verification`, () => { + before(() => { + // Address table has belongs to, has many & many-to-many + cy.openTableTab("Country", 25); + + cy.saveLocalStorage(); + // store base URL- to re-visit and delete form view later + cy.url().then((url) => { + storedURL = url; + generateViewLink("rowColUpdate"); + }); + }); - it(`Share GRID view : new row visible`, () => { - // verify row - cy.get(`.v-pagination > li:contains('5') button`).click(); - // wait for page rendering to complete - cy.get(".nc-grid-row").should("have.length", 10); - mainPage.getCell("Country", 10).contains("a").should("exist"); - }); + after(() => { + // close table + cy.restoreLocalStorage(); + cy.visit(storedURL, { + baseUrl: null, + }); + + // delete row + mainPage.getPagination(5).click(); + // wait for page rendering to complete + cy.get(".nc-grid-row").should("have.length", 10); + mainPage + .getRow(10) + .find(".mdi-checkbox-blank-outline") + .click({ force: true }); + mainPage.getCell("Country", 10).rightclick(); + cy.getActiveMenu().contains("Delete Selected Row").click(); + + // delete column + cy.get(`th:contains('dummy') .mdi-menu-down`) + .trigger("mouseover") + .click(); + cy.get(".nc-column-delete").click(); + cy.get("button:contains(Confirm)").click(); + + cy.toastWait("Update table successful"); + + mainPage.deleteCreatedViews(); + + // close table + cy.closeTableTab("Country"); + }); + + it(`Generate default Shared GRID view URL`, () => { + // add row + cy.get(".nc-add-new-row-btn").click({ force: true }); + cy.get("#data-table-form-Country > input") + .first() + .click() + .type("a"); + cy.contains("Save Row").filter("button").click({ force: true }); + cy.toastWait("updated successfully"); + + // add column + mainPage.addColumn("dummy", "Country"); + + // visit public view + cy.log(viewURL["rowColUpdate"]); + cy.restoreLocalStorage(); + cy.visit(viewURL["rowColUpdate"], { + baseUrl: null, + }); //5 + // wait for public view page to load! + // wait for page rendering to complete + cy.get(".nc-grid-row").should("have.length", 25); + }); + + it(`Share GRID view : new row visible`, () => { + // verify row + cy.get(`.v-pagination > li:contains('5') button`).click(); + // wait for page rendering to complete + cy.get(".nc-grid-row").should("have.length", 10); + mainPage.getCell("Country", 10).contains("a").should("exist"); + }); - it.skip(`Share GRID view : new column visible`, () => { - // verify column headers - cy.get('[data-col="dummy"]').should("exist"); + it.skip(`Share GRID view : new column visible`, () => { + // verify column headers + cy.get('[data-col="dummy"]').should("exist"); + }); }); - }); }; /** diff --git a/scripts/cypress/integration/common/5a_user_role.js b/scripts/cypress/integration/common/5a_user_role.js index d44c34b1ba..ffb0585a74 100644 --- a/scripts/cypress/integration/common/5a_user_role.js +++ b/scripts/cypress/integration/common/5a_user_role.js @@ -62,6 +62,8 @@ export const genTest = (apiType, dbType) => { cy.get(".nc-exp-imp-metadata").dblclick({ force: true }); cy.get(".nc-ui-acl-tab").click({ force: true }); + cy.snip("Meta_Tab3"); + // validate if it has 19 entries representing tables & views if (isPostgres()) cy.get(".nc-acl-table-row").should("have.length", 24); diff --git a/scripts/cypress/integration/common/6b_downloadCsv.js b/scripts/cypress/integration/common/6b_downloadCsv.js index 9b73521d72..51ded55192 100644 --- a/scripts/cypress/integration/common/6b_downloadCsv.js +++ b/scripts/cypress/integration/common/6b_downloadCsv.js @@ -9,12 +9,10 @@ export const genTest = (apiType, dbType) => { before(() => { // loginPage.loginAndOpenProject(type) cy.openTableTab("Country", 25); - cy.screenshot("6b-before"); }); after(() => { cy.closeTableTab("Country"); - cy.screenshot("6b-after"); }); it("Download verification- base view, default columns", () => { diff --git a/scripts/cypress/integration/common/6c_swagger_api.js b/scripts/cypress/integration/common/6c_swagger_api.js index d72283c572..40a8c9164a 100644 --- a/scripts/cypress/integration/common/6c_swagger_api.js +++ b/scripts/cypress/integration/common/6c_swagger_api.js @@ -4,224 +4,248 @@ import { roles } from "../../support/page_objects/projectConstants"; import { isTestSuiteActive } from "../../support/page_objects/projectConstants"; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; + if (!isTestSuiteActive(apiType, dbType)) return; - describe(`${apiType.toUpperCase()} : API List - Test preparation`, () => { - before(() => { - loginPage.loginAndOpenProject(apiType, dbType); - }); + describe(`${apiType.toUpperCase()} : API List - Test preparation`, () => { + before(() => { + loginPage.loginAndOpenProject(apiType, dbType); + }); - it("Open project & record swagger URL, AuthToken", () => { - let authToken = mainPage.getAuthToken(); - cy.url().then((url) => { - // retrieve project name from URL & use it to construct Swagger URL - // URL on homepage: http://localhost:3000/#/nc/externalrest_weUO?type=roles&dbalias=&name=Team%20%26%20Auth%20 - // [REST] Swagger URL: http://localhost:8080/nc/externalrest_weUO/db/swagger - // [GQL] http://localhost:8080/nc/externalgql_dgwx/v1/graphql - const projectName = url.split("/")[5].split("?")[0]; - let swaggerURL = ``; - if ("rest" == apiType) { - swaggerURL = `http://localhost:8080/nc/${projectName}/db/swagger`; - } else { - swaggerURL = `http://localhost:8080/nc/${projectName}/v1/graphql`; - } - - // exchange information between two tests using a file - // https://stackoverflow.com/questions/52050657/what-is-the-best-practice-of-pass-states-between-tests-in-cypress - // - cy.writeFile("shared.json", { - SWAGGER_URL: swaggerURL, - AUTH_TOKEN: authToken, + it("Open project & record swagger URL, AuthToken", () => { + let authToken = mainPage.getAuthToken(); + cy.url().then((url) => { + // retrieve project name from URL & use it to construct Swagger URL + // URL on homepage: http://localhost:3000/#/nc/externalrest_weUO?type=roles&dbalias=&name=Team%20%26%20Auth%20 + // [REST] Swagger URL: http://localhost:8080/nc/externalrest_weUO/db/swagger + // [GQL] http://localhost:8080/nc/externalgql_dgwx/v1/graphql + const projectName = url.split("/")[5].split("?")[0]; + let swaggerURL = ``; + if ("rest" == apiType) { + swaggerURL = `http://localhost:8080/nc/${projectName}/db/swagger`; + } else { + swaggerURL = `http://localhost:8080/nc/${projectName}/v1/graphql`; + } + + // exchange information between two tests using a file + // https://stackoverflow.com/questions/52050657/what-is-the-best-practice-of-pass-states-between-tests-in-cypress + // + cy.writeFile("shared.json", { + SWAGGER_URL: swaggerURL, + AUTH_TOKEN: authToken, + }); + }); }); - }); }); - }); - - if ("rest" == apiType) { - describe(`Swagger page, base verification`, () => { - // returns swagger button intended for - // - const getSwaggerButton = (tag, idx, desc) => { - return cy - .get(`#operations-tag-${tag}`) - .next() - .find(".opblock") - .eq(idx) - .find(`button:contains(${desc})`); - }; - - let Token; - - // basic authentication tag verification - // - it("Swagger URL access & basic validation", () => { - // retrieve information stored in previous IT block - // - cy.readFile("shared.json").then((jsonPayload) => { - let URL = jsonPayload.SWAGGER_URL; - Token = jsonPayload.AUTH_TOKEN; - - cy.visit(URL, { - baseUrl: null, - }).then(() => { - // wait to allow time for SWAGGER Library loading to finish - cy.log(Token); - - // validate; API order assumed - cy.get("#operations-tag-Authentication", { timeout: 20000 }) - .should("exist") - .next() - .find(".opblock") - .should("has.length", 9); - getSwaggerButton("Authentication", 0, "User login").should("exist"); - getSwaggerButton("Authentication", 1, "User signup").should( - "exist" - ); - getSwaggerButton("Authentication", 2, "Password Forgot").should( - "exist" - ); - getSwaggerButton("Authentication", 3, "Email validate link").should( - "exist" - ); - getSwaggerButton( - "Authentication", - 4, - "Validate password reset token" - ).should("exist"); - getSwaggerButton("Authentication", 5, "Password reset").should( - "exist" - ); - getSwaggerButton("Authentication", 6, "User details").should( - "exist" - ); - getSwaggerButton("Authentication", 7, "Update user details").should( - "exist" - ); - getSwaggerButton("Authentication", 8, "Update user details").should( - "exist" - ); - }); + + if ("rest" == apiType) { + describe(`Swagger page, base verification`, () => { + // returns swagger button intended for + // + const getSwaggerButton = (tag, idx, desc) => { + return cy + .get(`#operations-tag-${tag}`) + .next() + .find(".opblock") + .eq(idx) + .find(`button:contains(${desc})`); + }; + + let Token; + + // basic authentication tag verification + // + it("Swagger URL access & basic validation", () => { + // retrieve information stored in previous IT block + // + cy.readFile("shared.json").then((jsonPayload) => { + let URL = jsonPayload.SWAGGER_URL; + Token = jsonPayload.AUTH_TOKEN; + + cy.visit(URL, { + baseUrl: null, + }).then(() => { + // wait to allow time for SWAGGER Library loading to finish + cy.log(Token); + + // cy.snip("Swagger"); + + // validate; API order assumed + cy.get("#operations-tag-Authentication", { + timeout: 20000, + }) + .should("exist") + .next() + .find(".opblock") + .should("has.length", 9); + getSwaggerButton( + "Authentication", + 0, + "User login" + ).should("exist"); + getSwaggerButton( + "Authentication", + 1, + "User signup" + ).should("exist"); + getSwaggerButton( + "Authentication", + 2, + "Password Forgot" + ).should("exist"); + getSwaggerButton( + "Authentication", + 3, + "Email validate link" + ).should("exist"); + getSwaggerButton( + "Authentication", + 4, + "Validate password reset token" + ).should("exist"); + getSwaggerButton( + "Authentication", + 5, + "Password reset" + ).should("exist"); + getSwaggerButton( + "Authentication", + 6, + "User details" + ).should("exist"); + getSwaggerButton( + "Authentication", + 7, + "Update user details" + ).should("exist"); + getSwaggerButton( + "Authentication", + 8, + "Update user details" + ).should("exist"); + }); + }); + }); + + it("Authorize success: Valid token", () => { + // authorize button, feed token, click authorize + cy.get('[class="btn authorize unlocked"]').click(); + cy.get("input").type(Token); + cy.get(".auth-btn-wrapper > .authorize").click(); + + // Response: "Authorized" should exist on DOM + cy.get(".auth-container") + .contains("Authorized") + .should("exist"); + cy.get(".btn-done").click(); + + // Authorize button is LOCKED now + cy.get('[class="btn authorize locked"]').should("exist"); + }); + + it("Execute Authentication (valid token case) > GET: User details API", () => { + // Auth> User details API + getSwaggerButton("Authentication", 6, "User details").click(); + + // "Try it out" button, followed by "Execute" + cy.get(".try-out > .btn").click(); + cy.get(".execute-wrapper > .btn").click(); + + // check response: validate email credentials + cy.get(".highlight-code > .microlight") + .contains("email") + .should("exist"); + cy.get(".highlight-code > .microlight") + .contains(roles.owner.credentials.username) + .should("exist"); + + // reset operations (clear, cancel, windback User details tab) + cy.get(".btn-clear").click(); + cy.get(".try-out > .btn").click(); + getSwaggerButton("Authentication", 6, "User details").click(); + }); + + it("Logout post authorization", () => { + // authorize button, logout + cy.get('[class="btn authorize locked"]').click(); + cy.get('.auth-btn-wrapper > button:contains("Logout")').click(); + cy.get(".btn-done").click(); + + // Authorize button is UNLOCKED now + cy.get('[class="btn authorize unlocked"]').should("exist"); + }); + + it("Execute Authentication (logout case) > GET: User details API", () => { + // Auth> User details API + getSwaggerButton("Authentication", 6, "User details").click(); + + // "Try it out" button, followed by "Execute" + cy.get(".try-out > .btn").click(); + cy.get(".execute-wrapper > .btn").click(); + + // check response: email credentials shouldnt exist. should display 'guest:true' + cy.get(".highlight-code > .microlight") + .contains("guest") + .should("exist"); + cy.get(".highlight-code > .microlight") + .contains("email") + .should("not.exist"); + cy.get(".highlight-code > .microlight") + .contains(roles.owner.credentials.username) + .should("not.exist"); + + // reset operations (clear, cancel, windback User details tab) + cy.get(".btn-clear").click(); + cy.get(".try-out > .btn").click(); + getSwaggerButton("Authentication", 6, "User details").click(); + }); + + it("Authorize failure: invalid token", () => { + // authorize button, feed *invalid* token, click authorize + cy.get('[class="btn authorize unlocked"]').click(); + cy.get("input").type("xyz"); + cy.get(".auth-btn-wrapper > .authorize").click(); + + // Response: "Authorized" should *not* exist on DOM + // TBD: cy.get('.auth-container').contains('Authorized').should('not.exist') + cy.get(".btn-done").click(); + + // Authorize button should be UNLOCKED now + // TBD: cy.get('[class="btn authorize unlocked"]').should('exist') + }); + + it("Execute Authentication (invalid token case) > GET: User details API", () => { + // Auth> User details API + getSwaggerButton("Authentication", 6, "User details").click(); + + // "Try it out" button, followed by "Execute" + cy.get(".try-out > .btn").click(); + cy.get(".execute-wrapper > .btn").click(); + + // check response: email credentials shouldnt exist. should display 'guest:true' + cy.get(".highlight-code > .microlight") + .contains("guest") + .should("exist"); + cy.get(".highlight-code > .microlight") + .contains("email") + .should("not.exist"); + cy.get(".highlight-code > .microlight") + .contains(roles.owner.credentials.username) + .should("not.exist"); + + // reset operations (clear, cancel, windback User details tab) + cy.get(".btn-clear").click(); + cy.get(".try-out > .btn").click(); + getSwaggerButton("Authentication", 6, "User details").click(); + }); + + // clean-up created file (shared.json) + // after(() => { + // cy.exec("del shared.json").then(()=> { + // cy.log("file cleaned up!") + // }) + // }) }); - }); - - it("Authorize success: Valid token", () => { - // authorize button, feed token, click authorize - cy.get('[class="btn authorize unlocked"]').click(); - cy.get("input").type(Token); - cy.get(".auth-btn-wrapper > .authorize").click(); - - // Response: "Authorized" should exist on DOM - cy.get(".auth-container").contains("Authorized").should("exist"); - cy.get(".btn-done").click(); - - // Authorize button is LOCKED now - cy.get('[class="btn authorize locked"]').should("exist"); - }); - - it("Execute Authentication (valid token case) > GET: User details API", () => { - // Auth> User details API - getSwaggerButton("Authentication", 6, "User details").click(); - - // "Try it out" button, followed by "Execute" - cy.get(".try-out > .btn").click(); - cy.get(".execute-wrapper > .btn").click(); - - // check response: validate email credentials - cy.get(".highlight-code > .microlight") - .contains("email") - .should("exist"); - cy.get(".highlight-code > .microlight") - .contains(roles.owner.credentials.username) - .should("exist"); - - // reset operations (clear, cancel, windback User details tab) - cy.get(".btn-clear").click(); - cy.get(".try-out > .btn").click(); - getSwaggerButton("Authentication", 6, "User details").click(); - }); - - it("Logout post authorization", () => { - // authorize button, logout - cy.get('[class="btn authorize locked"]').click(); - cy.get('.auth-btn-wrapper > button:contains("Logout")').click(); - cy.get(".btn-done").click(); - - // Authorize button is UNLOCKED now - cy.get('[class="btn authorize unlocked"]').should("exist"); - }); - - it("Execute Authentication (logout case) > GET: User details API", () => { - // Auth> User details API - getSwaggerButton("Authentication", 6, "User details").click(); - - // "Try it out" button, followed by "Execute" - cy.get(".try-out > .btn").click(); - cy.get(".execute-wrapper > .btn").click(); - - // check response: email credentials shouldnt exist. should display 'guest:true' - cy.get(".highlight-code > .microlight") - .contains("guest") - .should("exist"); - cy.get(".highlight-code > .microlight") - .contains("email") - .should("not.exist"); - cy.get(".highlight-code > .microlight") - .contains(roles.owner.credentials.username) - .should("not.exist"); - - // reset operations (clear, cancel, windback User details tab) - cy.get(".btn-clear").click(); - cy.get(".try-out > .btn").click(); - getSwaggerButton("Authentication", 6, "User details").click(); - }); - - it("Authorize failure: invalid token", () => { - // authorize button, feed *invalid* token, click authorize - cy.get('[class="btn authorize unlocked"]').click(); - cy.get("input").type("xyz"); - cy.get(".auth-btn-wrapper > .authorize").click(); - - // Response: "Authorized" should *not* exist on DOM - // TBD: cy.get('.auth-container').contains('Authorized').should('not.exist') - cy.get(".btn-done").click(); - - // Authorize button should be UNLOCKED now - // TBD: cy.get('[class="btn authorize unlocked"]').should('exist') - }); - - it("Execute Authentication (invalid token case) > GET: User details API", () => { - // Auth> User details API - getSwaggerButton("Authentication", 6, "User details").click(); - - // "Try it out" button, followed by "Execute" - cy.get(".try-out > .btn").click(); - cy.get(".execute-wrapper > .btn").click(); - - // check response: email credentials shouldnt exist. should display 'guest:true' - cy.get(".highlight-code > .microlight") - .contains("guest") - .should("exist"); - cy.get(".highlight-code > .microlight") - .contains("email") - .should("not.exist"); - cy.get(".highlight-code > .microlight") - .contains(roles.owner.credentials.username) - .should("not.exist"); - - // reset operations (clear, cancel, windback User details tab) - cy.get(".btn-clear").click(); - cy.get(".try-out > .btn").click(); - getSwaggerButton("Authentication", 6, "User details").click(); - }); - - // clean-up created file (shared.json) - // after(() => { - // cy.exec("del shared.json").then(()=> { - // cy.log("file cleaned up!") - // }) - // }) - }); - } + } }; /** diff --git a/scripts/cypress/integration/common/6d_language_validation.js b/scripts/cypress/integration/common/6d_language_validation.js index 871456d793..d98643af96 100644 --- a/scripts/cypress/integration/common/6d_language_validation.js +++ b/scripts/cypress/integration/common/6d_language_validation.js @@ -9,7 +9,7 @@ export const genTest = (apiType, dbType) => { before(() => { //loginPage.signIn(roles.owner.credentials) mainPage.toolBarTopLeft(mainPage.HOME).click(); - cy.screenshot("6d-1"); + cy.screenshot("Debug 6d-1", { overwrite: true }); }); const langVerification = (idx, lang) => { @@ -19,9 +19,12 @@ export const genTest = (apiType, dbType) => { // toggle menu as per index cy.get(".nc-menu-translate").click(); + + cy.snipActiveMenu("Menu_Translation"); + cy.getActiveMenu().find(".v-list-item").eq(idx).click(); - cy.screenshot("6d-2"); + cy.screenshot("Debug 6d-2", { overwrite: true }); // basic validations // 1. Page title: "My Projects" diff --git a/scripts/cypress/integration/common/6e_project_operations.js b/scripts/cypress/integration/common/6e_project_operations.js index f9a342b985..723261352f 100644 --- a/scripts/cypress/integration/common/6e_project_operations.js +++ b/scripts/cypress/integration/common/6e_project_operations.js @@ -3,69 +3,78 @@ import { isXcdb, roles } from "../../support/page_objects/projectConstants"; import { isTestSuiteActive } from "../../support/page_objects/projectConstants"; export const genTest = (apiType, dbType) => { - describe(`${apiType.toUpperCase()} Project operations`, () => { - if (!isTestSuiteActive(apiType, dbType)) return; + describe(`${apiType.toUpperCase()} Project operations`, () => { + if (!isTestSuiteActive(apiType, dbType)) return; - before(() => { - loginPage.signIn(roles.owner.credentials); - }); + before(() => { + loginPage.signIn(roles.owner.credentials); + }); - it("Stop Project", () => { - //cy.visit('./#/projects') - cy.get(`.nc-${apiType}-project-row .mdi-stop-circle-outline`, { - timeout: 10000, - }) - .should("exist") - .last() - .invoke("show") - .click(); - cy.contains("Submit").closest("button").click(); + it("Stop Project", () => { + //cy.visit('./#/projects') + cy.get(`.nc-${apiType}-project-row .mdi-stop-circle-outline`, { + timeout: 10000, + }) + .should("exist") + .last() + .invoke("show") + .click(); + cy.snipActiveModal("Modal_StopProject"); + cy.contains("Submit").closest("button").click(); - cy.toastWait("stopped successfully"); - }); + cy.toastWait("stopped successfully"); + }); - it("Start Project", () => { - //cy.visit('./#/projects') - cy.get(`.nc-${apiType}-project-row .mdi-play-circle-outline`, { - timeout: 10000, - }) - .should("exist") - .last() - .invoke("show") - .click(); - cy.contains("Submit").closest("button").click(); + it("Start Project", () => { + //cy.visit('./#/projects') + cy.get(`.nc-${apiType}-project-row .mdi-play-circle-outline`, { + timeout: 10000, + }) + .should("exist") + .last() + .invoke("show") + .click(); + cy.snipActiveModal("Modal_StartProject"); - cy.toastWait("started successfully"); - }); + cy.contains("Submit").closest("button").click(); - it("Restart Project", () => { - if (!isXcdb()) { - //cy.visit('./#/projects') - cy.get(`.nc-${apiType}-project-row .mdi-restart`, { timeout: 10000 }) - .should("exist") - .last() - .invoke("show") - .click(); - cy.contains("Submit").closest("button").click(); + cy.toastWait("started successfully"); + }); - cy.toastWait("restarted successfully"); - } - }); + it("Restart Project", () => { + if (!isXcdb()) { + //cy.visit('./#/projects') + cy.get(`.nc-${apiType}-project-row .mdi-restart`, { + timeout: 10000, + }) + .should("exist") + .last() + .invoke("show") + .click(); + cy.snipActiveModal("Modal_RestartProject"); + + cy.contains("Submit").closest("button").click(); + + cy.toastWait("restarted successfully"); + } + }); + + it("Delete Project", () => { + //cy.visit('./#/projects') + cy.get(`.nc-${apiType}-project-row .mdi-delete-circle-outline`, { + timeout: 10000, + }) + .should("exist") + .last() + .invoke("show") + .click(); + cy.snipActiveModal("Modal_DeleteProject"); - it("Delete Project", () => { - //cy.visit('./#/projects') - cy.get(`.nc-${apiType}-project-row .mdi-delete-circle-outline`, { - timeout: 10000, - }) - .should("exist") - .last() - .invoke("show") - .click(); - cy.contains("Submit").closest("button").click(); + cy.contains("Submit").closest("button").click(); - cy.toastWait("deleted successfully"); + cy.toastWait("deleted successfully"); + }); }); - }); }; /** diff --git a/scripts/cypress/integration/common/6g_base_share.js b/scripts/cypress/integration/common/6g_base_share.js index 913df20820..08e86ab284 100644 --- a/scripts/cypress/integration/common/6g_base_share.js +++ b/scripts/cypress/integration/common/6g_base_share.js @@ -3,75 +3,78 @@ import { projectsPage } from "../../support/page_objects/navigation"; import { loginPage } from "../../support/page_objects/navigation"; import { isTestSuiteActive } from "../../support/page_objects/projectConstants"; import { - _advSettings, - _editSchema, - _editData, - _editComment, - _viewMenu, - _topRightMenu, + _advSettings, + _editSchema, + _editData, + _editComment, + _viewMenu, + _topRightMenu, } from "../spec/roleValidation.spec"; let linkText = ""; export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; + if (!isTestSuiteActive(apiType, dbType)) return; - const permissionValidation = (roleType) => { - it(`${roleType}: Visit base shared URL`, () => { - cy.log(linkText); + const permissionValidation = (roleType) => { + it(`${roleType}: Visit base shared URL`, () => { + cy.log(linkText); - // visit URL & wait for page load to complete - cy.visit(linkText, { - baseUrl: null, - }); - projectsPage.waitHomePageLoad(); + // visit URL & wait for page load to complete + cy.visit(linkText, { + baseUrl: null, + }); + projectsPage.waitHomePageLoad(); - cy.closeTableTab("Actor"); - }); + cy.closeTableTab("Actor"); + }); - it(`${roleType}: Validate access permissions: advance menu`, () => { - _advSettings(roleType, false); - }); + it(`${roleType}: Validate access permissions: advance menu`, () => { + _advSettings(roleType, false); + }); - it(`${roleType}: Validate access permissions: edit schema`, () => { - _editSchema(roleType, false); - }); + it(`${roleType}: Validate access permissions: edit schema`, () => { + _editSchema(roleType, false); + }); - it(`${roleType}: Validate access permissions: edit data`, () => { - _editData(roleType, false); - }); + it(`${roleType}: Validate access permissions: edit data`, () => { + _editData(roleType, false); + }); - it(`${roleType}: Validate access permissions: edit comments`, () => { - _editComment(roleType, false); - }); + it(`${roleType}: Validate access permissions: edit comments`, () => { + _editComment(roleType, false); + }); - it(`${roleType}: Validate access permissions: view's menu`, () => { - _viewMenu(roleType, false); - }); - }; - - describe(`${apiType.toUpperCase()} Base VIEW share`, () => { - it(`Generate base share URL`, () => { - // click SHARE - cy.get(".nc-topright-menu").find(".nc-menu-share").click(); - - // Click on readonly base text - cy.getActiveModal().find(".nc-disable-shared-base").click(); - - // Select 'Readonly link' - cy.getActiveMenu() - .find(".caption") - .contains("Anyone with the link") - .click(); - - // Copy URL - cy.getActiveModal() - .find(".nc-url") - .then(($obj) => { - cy.log($obj[0]); - linkText = $obj[0].innerText.trim(); - - const htmlFile = ` + it(`${roleType}: Validate access permissions: view's menu`, () => { + _viewMenu(roleType, false); + }); + }; + + describe(`${apiType.toUpperCase()} Base VIEW share`, () => { + it(`Generate base share URL`, () => { + // click SHARE + cy.get(".nc-topright-menu").find(".nc-menu-share").click(); + + cy.snipActiveModal("Modal_BaseShare"); + + // Click on readonly base text + cy.getActiveModal().find(".nc-disable-shared-base").click(); + + // Select 'Readonly link' + cy.snipActiveMenu("Menu_ShareLink"); + cy.getActiveMenu() + .find(".caption") + .contains("Anyone with the link") + .click(); + + // Copy URL + cy.getActiveModal() + .find(".nc-url") + .then(($obj) => { + cy.log($obj[0]); + linkText = $obj[0].innerText.trim(); + + const htmlFile = ` @@ -87,55 +90,63 @@ style="background: transparent; "> `; - cy.writeFile( - "scripts/cypress/fixtures/sampleFiles/iFrame.html", - htmlFile - ); + cy.writeFile( + "scripts/cypress/fixtures/sampleFiles/iFrame.html", + htmlFile + ); + }); }); - }); - permissionValidation("viewer"); + permissionValidation("viewer"); - it("Update to EDITOR base share link", () => { - loginPage.loginAndOpenProject(apiType, dbType); + it("Update to EDITOR base share link", () => { + loginPage.loginAndOpenProject(apiType, dbType); - // click SHARE - cy.get(".nc-topright-menu").find(".nc-menu-share").click(); + // click SHARE + cy.get(".nc-topright-menu").find(".nc-menu-share").click(); - cy.getActiveModal().find(".nc-shared-base-role").click(); + cy.getActiveModal().find(".nc-shared-base-role").click(); - cy.getActiveMenu().find('[role="menuitem"]').contains("Editor").click(); - }); + cy.getActiveMenu() + .find('[role="menuitem"]') + .contains("Editor") + .click(); + }); - permissionValidation("editor"); - - it("Generate & verify embed HTML IFrame", { baseUrl: null }, () => { - // open iFrame html - cy.visit("scripts/cypress/fixtures/sampleFiles/iFrame.html"); - - // wait for iFrame to load - cy.frameLoaded(".nc-embed"); - - // for GQL- additionally close GQL Client window - if (apiType === "graphql") { - cy.iframe().find(`[title="Graphql Client"] > button.mdi-close`).click(); - } - - // validation for base menu opitons - cy.iframe().find(".nc-project-tree").should("exist"); - cy.iframe().find(".nc-fields-menu-btn").should("exist"); - cy.iframe().find(".nc-sort-menu-btn").should("exist"); - cy.iframe().find(".nc-filter-menu-btn").should("exist"); - cy.iframe().find(".nc-actions-menu-btn").should("exist"); - - // validate data (row-1) - mainPage - .getIFrameCell("FirstName", 1) - .contains("PENELOPE") - .should("exist"); - mainPage.getIFrameCell("LastName", 1).contains("GUINESS").should("exist"); + permissionValidation("editor"); + + it("Generate & verify embed HTML IFrame", { baseUrl: null }, () => { + // open iFrame html + cy.visit("scripts/cypress/fixtures/sampleFiles/iFrame.html"); + + // wait for iFrame to load + cy.frameLoaded(".nc-embed"); + + // for GQL- additionally close GQL Client window + if (apiType === "graphql") { + cy.iframe() + .find(`[title="Graphql Client"] > button.mdi-close`) + .click(); + } + + // validation for base menu opitons + cy.iframe().find(".nc-project-tree").should("exist"); + cy.iframe().find(".nc-fields-menu-btn").should("exist"); + cy.iframe().find(".nc-sort-menu-btn").should("exist"); + cy.iframe().find(".nc-filter-menu-btn").should("exist"); + cy.iframe().find(".nc-actions-menu-btn").should("exist"); + + // validate data (row-1) + mainPage + .getIFrameCell("FirstName", 1) + .contains("PENELOPE") + .should("exist"); + mainPage + .getIFrameCell("LastName", 1) + .contains("GUINESS") + .should("exist"); + }); }); - }); }; /** diff --git a/scripts/cypress/integration/common/7a_create_project_from_excel.js b/scripts/cypress/integration/common/7a_create_project_from_excel.js index d2a5bd3ca0..a3e9dbfa05 100644 --- a/scripts/cypress/integration/common/7a_create_project_from_excel.js +++ b/scripts/cypress/integration/common/7a_create_project_from_excel.js @@ -4,8 +4,8 @@ import { projectsPage } from "../../support/page_objects/navigation"; import { mainPage } from "../../support/page_objects/mainPage"; import { - roles, - isTestSuiteActive, + roles, + isTestSuiteActive, } from "../../support/page_objects/projectConstants"; // stores sheet names (table name) @@ -21,29 +21,29 @@ let filepath = `sampleFiles/simple.xlsx`; // let UrlFilePath = `sampleFiles/Financial Sample.xlsx` let expectedData = { - 0: ["number", "Number"], - 1: ["float", "Decimal"], - 2: ["text", "SingleLineText"], + 0: ["number", "Number"], + 1: ["float", "Decimal"], + 2: ["text", "SingleLineText"], }; // column names with spaces will be converted to include _ let UrlFileExpectedData = { - 0: ["Segment", "SingleSelect", ["Government"]], - 1: ["Country", "SingleSelect", ["Canada"]], - 2: ["Product", "SingleSelect", ["Carretera"]], - 3: ["Discount_Band", "SingleSelect", ["None"]], - 4: ["Units_Sold", "Decimal", [1618.5]], - 5: ["Manufacturing_Price", "Number", [3]], - 6: ["Sale_Price", "Number", [20]], - 7: ["Gross_Sales", "Decimal", [32370]], - 8: ["Discounts", "Decimal", [0]], - 9: ["Sales", "Decimal", [32370]], - 10: ["COGS", "Decimal", [16185]], - 11: ["Profit", "Decimal", [16185]], - 12: ["Date", "Date", ["2014-01-01"]], - 13: ["Month_Number", "Number", [1]], - 14: ["Month_Name", "SingleSelect", ["January"]], - 15: ["Year", "SingleSelect", [2014]], + 0: ["Segment", "SingleSelect", ["Government"]], + 1: ["Country", "SingleSelect", ["Canada"]], + 2: ["Product", "SingleSelect", ["Carretera"]], + 3: ["Discount_Band", "SingleSelect", ["None"]], + 4: ["Units_Sold", "Decimal", [1618.5]], + 5: ["Manufacturing_Price", "Number", [3]], + 6: ["Sale_Price", "Number", [20]], + 7: ["Gross_Sales", "Decimal", [32370]], + 8: ["Discounts", "Decimal", [0]], + 9: ["Sales", "Decimal", [32370]], + 10: ["COGS", "Decimal", [16185]], + 11: ["Profit", "Decimal", [16185]], + 12: ["Date", "Date", ["2014-01-01"]], + 13: ["Month_Number", "Number", [1]], + 14: ["Month_Name", "SingleSelect", ["January"]], + 15: ["Year", "SingleSelect", [2014]], }; // let filepath = `sampleFiles/sample.xlsx` @@ -64,259 +64,281 @@ let UrlFileExpectedData = { // } export const genTest = (apiType, dbType) => { - if (!isTestSuiteActive(apiType, dbType)) return; - - describe(`Import from excel`, () => { - before(() => { - cy.task("readSheetList", { - file: `./scripts/cypress/fixtures/${filepath}`, - }).then((rows) => { - cy.log(rows); - sheetList = rows; - }); - - cy.task("readXlsx", { - file: `./scripts/cypress/fixtures/${filepath}`, - sheet: "Sheet2", - }).then((rows) => { - cy.log(rows); - sheetData = rows; - }); - - // cy.task('readXlsx', { file: `./scripts/cypress/fixtures/${UrlFilePath}`, sheet: "Sheet1" }) - // .then((rows) => { - // cy.log(rows) - // UrlSheetData = rows - // }) - }); + if (!isTestSuiteActive(apiType, dbType)) return; + + describe(`Import from excel`, () => { + before(() => { + cy.task("readSheetList", { + file: `./scripts/cypress/fixtures/${filepath}`, + }).then((rows) => { + cy.log(rows); + sheetList = rows; + }); - it("File Upload: Upload excel as template", () => { - mainPage.toolBarTopLeft(mainPage.HOME).click(); + cy.task("readXlsx", { + file: `./scripts/cypress/fixtures/${filepath}`, + sheet: "Sheet2", + }).then((rows) => { + cy.log(rows); + sheetData = rows; + }); - // click on "New Project" - cy.get(":nth-child(5) > .v-btn", { timeout: 20000 }).click(); + // cy.task('readXlsx', { file: `./scripts/cypress/fixtures/${UrlFilePath}`, sheet: "Sheet1" }) + // .then((rows) => { + // cy.log(rows) + // UrlSheetData = rows + // }) + }); - // Subsequent form, select (+ Create) option - cy.get(".nc-create-project-from-excel", { timeout: 20000 }).click({ - force: true, - }); + it("File Upload: Upload excel as template", () => { + mainPage.toolBarTopLeft(mainPage.HOME).click(); - cy.get(".nc-excel-import-input").attachFile(filepath); - cy.get(".nc-btn-use-template", { timeout: 120000 }).should("exist"); - }); + // click on "New Project" + cy.get(":nth-child(5) > .v-btn", { timeout: 20000 }).click(); - it("File Upload: Verify pre-load template page", () => { - cy.getActiveContentModal() - .find(".v-expansion-panel") - .then((sheets) => { - for (let i = 0; i < sheets.length; i++) { - // verify if all sheet names are correct - // cy.wrap(sheets[i]).find('.title').then((blk) => { - // cy.log(blk.text().trim()) - // expect(blk.text().trim()).to.equal(sheetList[i]) - // }) + // Subsequent form, select (+ Create) option + cy.get(".nc-create-project-from-excel", { timeout: 20000 }).click({ + force: true, + }); + + cy.snipActiveModal("Modal_CreateFromExcel"); - cy.wrap(sheets[i]).contains(sheetList[i]).should("exist"); - - // for each sheet, expand to verify table names & their data types - cy.wrap(sheets[i]).find(".mdi-chevron-down").click(); - - // wait for 4 DOM rows to become visible, corresponding to 4 column names in excel - // change to avoid static wait - cy.get(".v-data-table").find("tr:visible").should("have.length", 4); - - cy.get(".v-data-table") - .find("tr:visible") - .then((row) => { - for (let j = 1; j < row.length; j++) { - // column name to match input in excel - cy.wrap(row[j]) - .find('[placeholder="Column name"]') - .then((obj) => { - cy.log(obj[0].value); - expect(obj[0].value).to.equal(expectedData[j - 1][0]); - }); - - // datatype to match expected output - cy.wrap(row[j]) - .find("span.caption") - .then((obj) => { - cy.log(obj[0].innerText); - expect(obj[0].innerText).to.equal(expectedData[j - 1][1]); - }); - } - }); - - // unwind - cy.wrap(sheets[i]).find(".mdi-chevron-down").click(); - } + cy.get(".nc-excel-import-input").attachFile(filepath); + cy.get(".nc-btn-use-template", { timeout: 120000 }).should("exist"); }); - }); - it("File Upload: Verify loaded data", () => { - // create rest/ gql project - cy.get(".nc-btn-use-template", { timeout: 120000 }).click(); - // if (type == 'rest') { - // cy.getActiveMenu().find('[role="menuitem"]').contains('REST').click() - // } else { - // cy.getActiveMenu().find('[role="menuitem"]').contains('GQL').click() - // } - - // wait for loading to be completed - projectsPage.waitHomePageLoad(); - - // open sheet & validate contents - // sheetData contains data read from excel in format - // 0: { float: 1.1, number: 1, text: "abc" } - // 1: { float: 1.2, number: 0, text: "def" } - - cy.openTableTab("Sheet2", 2); - for (const [key, value] of Object.entries(expectedData)) { - mainPage - .getCell(value[0], 1) - .contains(sheetData[0][value[0]]) - .should("exist"); - mainPage - .getCell(value[0], 2) - .contains(sheetData[1][value[0]]) - .should("exist"); - } - cy.closeTableTab("Sheet2"); - - cy.openTableTab("Sheet3", 2); - for (const [key, value] of Object.entries(expectedData)) { - mainPage - .getCell(value[0], 1) - .contains(sheetData[0][value[0]]) - .should("exist"); - mainPage - .getCell(value[0], 2) - .contains(sheetData[1][value[0]]) - .should("exist"); - } - cy.closeTableTab("Sheet3"); - - // delete project once all operations are completed - mainPage.toolBarTopLeft(mainPage.HOME).click(); - cy.get(`.nc-${apiType}-project-row .mdi-delete-circle-outline`, { - timeout: 10000, - }) - .should("exist") - .last() - .invoke("show") - .click(); - cy.contains("Submit").closest("button").click(); - }); + it("File Upload: Verify pre-load template page", () => { + cy.snip("ExcelImport"); + cy.getActiveContentModal() + .find(".v-expansion-panel") + .then((sheets) => { + for (let i = 0; i < sheets.length; i++) { + // verify if all sheet names are correct + // cy.wrap(sheets[i]).find('.title').then((blk) => { + // cy.log(blk.text().trim()) + // expect(blk.text().trim()).to.equal(sheetList[i]) + // }) + + cy.wrap(sheets[i]) + .contains(sheetList[i]) + .should("exist"); + + // for each sheet, expand to verify table names & their data types + cy.wrap(sheets[i]).find(".mdi-chevron-down").click(); + + // wait for 4 DOM rows to become visible, corresponding to 4 column names in excel + // change to avoid static wait + cy.get(".v-data-table") + .find("tr:visible") + .should("have.length", 4); + + cy.get(".v-data-table") + .find("tr:visible") + .then((row) => { + for (let j = 1; j < row.length; j++) { + // column name to match input in excel + cy.wrap(row[j]) + .find('[placeholder="Column name"]') + .then((obj) => { + cy.log(obj[0].value); + expect(obj[0].value).to.equal( + expectedData[j - 1][0] + ); + }); + + // datatype to match expected output + cy.wrap(row[j]) + .find("span.caption") + .then((obj) => { + cy.log(obj[0].innerText); + expect(obj[0].innerText).to.equal( + expectedData[j - 1][1] + ); + }); + } + }); + + // unwind + cy.wrap(sheets[i]).find(".mdi-chevron-down").click(); + } + }); + }); - it("URL: Upload excel as template", () => { - // click on "New Project" - cy.get(":nth-child(5) > .v-btn", { timeout: 20000 }).click(); - - // Subsequent form, select (+ Create) option - cy.get(".nc-create-project-from-excel", { timeout: 20000 }).click({ - force: true, - }); - - cy.getActiveModal().find(".caption").contains("URL").click(); - cy.get(".nc-excel-import-tab-item") - .find('input[type="url"]') - .click() - .type(URL); - cy.get(".nc-excel-import-tab-item") - .find("button") - .contains("Load") - .click(); - - cy.get(".nc-btn-use-template", { timeout: 120000 }).should("exist"); - }); + it("File Upload: Verify loaded data", () => { + // create rest/ gql project + cy.get(".nc-btn-use-template", { timeout: 120000 }).click(); + // if (type == 'rest') { + // cy.getActiveMenu().find('[role="menuitem"]').contains('REST').click() + // } else { + // cy.getActiveMenu().find('[role="menuitem"]').contains('GQL').click() + // } + + // wait for loading to be completed + projectsPage.waitHomePageLoad(); + + // open sheet & validate contents + // sheetData contains data read from excel in format + // 0: { float: 1.1, number: 1, text: "abc" } + // 1: { float: 1.2, number: 0, text: "def" } + + cy.openTableTab("Sheet2", 2); + for (const [key, value] of Object.entries(expectedData)) { + mainPage + .getCell(value[0], 1) + .contains(sheetData[0][value[0]]) + .should("exist"); + mainPage + .getCell(value[0], 2) + .contains(sheetData[1][value[0]]) + .should("exist"); + } + cy.closeTableTab("Sheet2"); + + cy.openTableTab("Sheet3", 2); + for (const [key, value] of Object.entries(expectedData)) { + mainPage + .getCell(value[0], 1) + .contains(sheetData[0][value[0]]) + .should("exist"); + mainPage + .getCell(value[0], 2) + .contains(sheetData[1][value[0]]) + .should("exist"); + } + cy.closeTableTab("Sheet3"); + + // delete project once all operations are completed + mainPage.toolBarTopLeft(mainPage.HOME).click(); + cy.get(`.nc-${apiType}-project-row .mdi-delete-circle-outline`, { + timeout: 10000, + }) + .should("exist") + .last() + .invoke("show") + .click(); + cy.contains("Submit").closest("button").click(); + }); - it("URL: Verify pre-load template page", () => { - cy.getActiveContentModal() - .find(".v-expansion-panel") - .then((sheets) => { - for (let i = 0; i < sheets.length; i++) { - // verify if all sheet names are correct - // cy.wrap(sheets[i]).find('.title').then((blk) => { - // cy.log(blk.text().trim()) - // expect(blk.text().trim()).to.equal('Sheet1') - // }) + it("URL: Upload excel as template", () => { + // click on "New Project" + cy.get(":nth-child(5) > .v-btn", { timeout: 20000 }).click(); - cy.wrap(sheets[i]).contains("Sheet1").should("exist"); - - // for each sheet, expand to verify table names & their data types - cy.wrap(sheets[i]).find(".mdi-chevron-down").click(); - cy.wait(3000).then(() => { - cy.get(".v-data-table") - .find("tr:visible") - .then((row) => { - // verification restricting to 10, as others need to be scrolled back into view - for (let j = 1; j <= 10 /*row.length*/; j++) { - // column name to match input in excel - cy.wrap(row[j]) - .find('[placeholder="Column name"]') - .then((obj) => { - cy.log(obj[0].value); - expect(obj[0].value).to.equal( - UrlFileExpectedData[j - 1][0] - ); - }); - - // datatype to match expected output - cy.wrap(row[j]) - .find("span.caption") - .then((obj) => { - cy.log(obj[0].innerText); - expect(obj[0].innerText).to.equal( - UrlFileExpectedData[j - 1][1] - ); - }); - } - }); + // Subsequent form, select (+ Create) option + cy.get(".nc-create-project-from-excel", { timeout: 20000 }).click({ + force: true, }); - // unwind - cy.wrap(sheets[i]).find(".mdi-chevron-down").click(); - } + cy.snipActiveModal("Modal_ImportExcelURL"); + cy.getActiveModal().find(".caption").contains("URL").click(); + cy.get(".nc-excel-import-tab-item") + .find('input[type="url"]') + .click() + .type(URL); + cy.get(".nc-excel-import-tab-item") + .find("button") + .contains("Load") + .click(); + + cy.get(".nc-btn-use-template", { timeout: 120000 }).should("exist"); }); - }); - it("URL: Verify loaded data", () => { - // create rest/ gql project - cy.get(".nc-btn-use-template", { timeout: 120000 }).click(); - - // wait for loading to be completed - projectsPage.waitHomePageLoad(); - - // open sheet & validate contents - // sheetData contains data read from excel in format - // 0: { float: 1.1, number: 1, text: "abc" } - // 1: { float: 1.2, number: 0, text: "def" } - - cy.openTableTab("Sheet1", 25); - let idx = 0; - for (const [key, value] of Object.entries(UrlFileExpectedData)) { - if (UrlFileExpectedData[idx][1] != "Date") - mainPage - .getCell(value[0], 1) - .contains(UrlFileExpectedData[idx++][2][0]) - .should("exist"); - } - cy.closeTableTab("Sheet1"); - }); + it("URL: Verify pre-load template page", () => { + cy.getActiveContentModal() + .find(".v-expansion-panel") + .then((sheets) => { + for (let i = 0; i < sheets.length; i++) { + // verify if all sheet names are correct + // cy.wrap(sheets[i]).find('.title').then((blk) => { + // cy.log(blk.text().trim()) + // expect(blk.text().trim()).to.equal('Sheet1') + // }) + + cy.wrap(sheets[i]).contains("Sheet1").should("exist"); + + // for each sheet, expand to verify table names & their data types + cy.wrap(sheets[i]).find(".mdi-chevron-down").click(); + cy.wait(3000).then(() => { + cy.get(".v-data-table") + .find("tr:visible") + .then((row) => { + // verification restricting to 10, as others need to be scrolled back into view + for ( + let j = 1; + j <= 10 /*row.length*/; + j++ + ) { + // column name to match input in excel + cy.wrap(row[j]) + .find('[placeholder="Column name"]') + .then((obj) => { + cy.log(obj[0].value); + expect(obj[0].value).to.equal( + UrlFileExpectedData[ + j - 1 + ][0] + ); + }); + + // datatype to match expected output + cy.wrap(row[j]) + .find("span.caption") + .then((obj) => { + cy.log(obj[0].innerText); + expect( + obj[0].innerText + ).to.equal( + UrlFileExpectedData[ + j - 1 + ][1] + ); + }); + } + }); + }); + + // unwind + cy.wrap(sheets[i]).find(".mdi-chevron-down").click(); + } + }); + }); - after(() => { - // delete project once all operations are completed - mainPage.toolBarTopLeft(mainPage.HOME).click(); - cy.get(`.nc-${apiType}-project-row .mdi-delete-circle-outline`, { - timeout: 10000, - }) - .should("exist") - .last() - .invoke("show") - .click(); - cy.contains("Submit").closest("button").click(); + it("URL: Verify loaded data", () => { + // create rest/ gql project + cy.get(".nc-btn-use-template", { timeout: 120000 }).click(); + + // wait for loading to be completed + projectsPage.waitHomePageLoad(); + + // open sheet & validate contents + // sheetData contains data read from excel in format + // 0: { float: 1.1, number: 1, text: "abc" } + // 1: { float: 1.2, number: 0, text: "def" } + + cy.openTableTab("Sheet1", 25); + let idx = 0; + for (const [key, value] of Object.entries(UrlFileExpectedData)) { + if (UrlFileExpectedData[idx][1] != "Date") + mainPage + .getCell(value[0], 1) + .contains(UrlFileExpectedData[idx++][2][0]) + .should("exist"); + } + cy.closeTableTab("Sheet1"); + }); + + after(() => { + // delete project once all operations are completed + mainPage.toolBarTopLeft(mainPage.HOME).click(); + cy.get(`.nc-${apiType}-project-row .mdi-delete-circle-outline`, { + timeout: 10000, + }) + .should("exist") + .last() + .invoke("show") + .click(); + cy.contains("Submit").closest("button").click(); + }); }); - }); }; // if (typeof require !== 'undefined') XLSX = require('xlsx'); diff --git a/scripts/cypress/support/commands.js b/scripts/cypress/support/commands.js index c66917ddda..0074b3ed71 100644 --- a/scripts/cypress/support/commands.js +++ b/scripts/cypress/support/commands.js @@ -56,11 +56,13 @@ Cypress.Commands.add("signinOrSignup", (_args) => { if ($body.find(".welcome-page").length > 0) { cy.wait(8000); cy.get("body").trigger("mousemove"); + cy.snip("LetsBegin"); cy.contains("Let's Begin").click(); cy.get('input[type="text"]', { timeout: 12000 }).type( args.username ); cy.get('input[type="password"]').type(args.password); + cy.snip("SignUp"); cy.get('button:contains("SIGN UP")').click(); // handle signin @@ -69,6 +71,7 @@ Cypress.Commands.add("signinOrSignup", (_args) => { args.username ); cy.get('input[type="password"]').type(args.password); + cy.snip("SignIn"); cy.get('button:contains("SIGN IN")').click(); } } @@ -86,6 +89,7 @@ Cypress.Commands.add("openOrCreateRestProject", (_args) => { // signin/signup cy.signinOrSignup(); cy.get(".nc-new-project-menu").should("exist"); + cy.snip("ProjectPage"); cy.get("body").then(($body) => { const filter = args.meta ? ".nc-meta-project-row" @@ -164,6 +168,8 @@ Cypress.Commands.add("openTableTab", (tn, rc) => { if (rc != 0) { cy.get(".nc-grid-row").should("have.length", rc); } + + cy.snip(`GridView_${tn}`); }); Cypress.Commands.add("closeTableTab", (tn) => { @@ -254,6 +260,9 @@ Cypress.Commands.add("createTable", (name) => { // .should("have.value", name.toLowerCase()); // } + cy.snip("CreateTable"); + cy.snipActiveModal("Modal_CreateTable"); + cy.get(".nc-create-table-card .nc-create-table-submit").first().click(); cy.toastWait(`Create table successful`); cy.get(`.project-tab:contains(${name})`).should("exist"); @@ -271,6 +280,7 @@ Cypress.Commands.add("deleteTable", (name, dbType) => { .click({ force: true }); cy.get(`.project-tab:contains(${name}):visible`).should("exist"); cy.get(".nc-table-delete-btn:visible").click(); + cy.snipActiveModal("Modal_DeleteTable"); cy.get("button:contains(Submit)").click(); // only for postgre project @@ -301,6 +311,7 @@ Cypress.Commands.add("renameTable", (oldName, newName) => { // feed new name cy.getActiveContentModal().find("input").clear().type(newName); + cy.snipActiveModal("Modal_RenameTable"); // submit cy.getActiveContentModal().find("button").contains("Submit").click(); @@ -327,6 +338,7 @@ Cypress.Commands.add("createColumn", (table, columnName) => { force: true, }); cy.get(".nc-column-name-input input").clear().type(columnName); + cy.getActiveMenu("Menu_CreateColumn"); cy.get(".nc-col-create-or-edit-card").contains("Save").click(); cy.get("th:contains(new_column)").should("exist"); }); @@ -375,6 +387,58 @@ Cypress.Commands.add("closeViewsTab", (vn) => { .click({ force: true }); }); +// Support for screen-shots +// + +let screenShotDb = []; + +// snip entire screen +Cypress.Commands.add("snip", (filename) => { + if ( + true === Cypress.env("screenshot") && + false === screenShotDb.includes(filename) + ) { + let storeName = `${screenShotDb.length}_${filename}`; + screenShotDb.push(filename); + cy.wait(1000); + cy.screenshot(storeName, { overwrite: true }); + } +}); + +// snip current modal +Cypress.Commands.add("snipActiveModal", (filename) => { + if ( + true === Cypress.env("screenshot") && + false === screenShotDb.includes(filename) + ) { + let storeName = `${screenShotDb.length}_${filename}`; + screenShotDb.push(filename); + cy.wait(1000); + // cy.getActiveModal().screenshot(filename, { + // padding: 0, + // overwrite: true, + // }); + cy.screenshot(storeName, { overwrite: true }); + } +}); + +// snip current menu +Cypress.Commands.add("snipActiveMenu", (filename) => { + if ( + true === Cypress.env("screenshot") && + false === screenShotDb.includes(filename) + ) { + let storeName = `${screenShotDb.length}_${filename}`; + screenShotDb.push(filename); + cy.wait(1000); + // cy.getActiveMenu().screenshot(filename, { + // padding: 0, + // overwrite: true, + // }); + cy.screenshot(storeName, { overwrite: true }); + } +}); + // Drag n Drop // refer: https://stackoverflow.com/a/55409853 /* diff --git a/scripts/cypress/support/page_objects/mainPage.js b/scripts/cypress/support/page_objects/mainPage.js index 6a81dc7848..a30bb7a36c 100644 --- a/scripts/cypress/support/page_objects/mainPage.js +++ b/scripts/cypress/support/page_objects/mainPage.js @@ -89,6 +89,9 @@ export class _mainPage { // click on New User button, feed details cy.get('button:contains("New User")').first().click(); + + cy.snip("NewUser"); + cy.get('label:contains("Email")') .next("input") .type(userCred.username) @@ -96,12 +99,14 @@ export class _mainPage { cy.get('label:contains("Select User roles")').click(); // opt-in requested role & submit + cy.snipActiveMenu("Menu_RoleType"); cy.getActiveMenu().contains(roleType).click(); cy.get(".nc-invite-or-save-btn").click(); cy.toastWait("Successfully updated the user details"); // get URL, invoke + cy.snipActiveModal("Modal_NewUserURL"); cy.getActiveModal() .find(".v-alert") .then(($obj) => { @@ -257,6 +262,9 @@ export class _mainPage { hideField = (field) => { cy.get(".nc-grid-header-cell").contains(field).should("be.visible"); cy.get(".nc-fields-menu-btn").click(); + + cy.snipActiveMenu("Menu_HideField"); + cy.get( `.menuable__content__active .v-list-item label:contains(${field})` ).click(); @@ -277,11 +285,16 @@ export class _mainPage { sortField = (field, criteria) => { cy.get(".nc-sort-menu-btn").click(); cy.contains("Add Sort Option").click(); + + cy.snipActiveMenu("Menu_SortField"); + cy.get(".nc-sort-field-select div").first().click(); + cy.snipActiveMenu("Menu_SortField_fieldSelection"); cy.get(`.menuable__content__active .v-list-item:contains(${field})`) .first() .click(); cy.get(".nc-sort-dir-select div").first().click(); + cy.snipActiveMenu("Menu_SortField_criteriaSelection"); cy.get( `.menuable__content__active .v-list-item:contains(${criteria})` ).click(); @@ -297,13 +310,18 @@ export class _mainPage { filterField = (field, operation, value) => { cy.get(".nc-filter-menu-btn").click(); cy.contains("Add Filter").click(); + cy.snipActiveMenu("Menu_FilterField"); cy.get(".nc-filter-field-select").last().click(); + cy.snipActiveMenu("Menu_FilterField-fieldSelect"); + cy.getActiveMenu() .find(`.v-list-item:contains(${field})`) .first() .click(); cy.get(".nc-filter-operation-select").last().click(); + cy.snipActiveMenu("Menu_FilterField-operationSelect"); + cy.getActiveMenu().find(`.v-list-item:contains(${operation})`).click(); if (operation != "is null" && operation != "is not null") { cy.get(".nc-filter-value-select input:text") @@ -343,6 +361,8 @@ export class _mainPage { // cy.getActiveMenu().find(".v-list-item").contains("Views List").click(); this.shareViewList().click(); + cy.snipActiveModal("Modal_ShareViewList"); + cy.wait(1000); // cy.get('.container').find('button.mdi-delete-outline') @@ -379,6 +399,7 @@ export class _mainPage { // downloadAndVerifyCsv = (filename, verifyCsv) => { cy.get(".nc-actions-menu-btn").click(); + cy.snipActiveMenu("Menu_ActionsMenu"); cy.get( `.menuable__content__active .v-list-item span:contains("Download as CSV")` ).click(); @@ -422,6 +443,9 @@ export class _mainPage { // open Project metadata tab // this.navigationDraw(this.PROJ_METADATA).click(); + + cy.snip("Meta_Tab0"); + cy.get(".nc-meta-mgmt-metadata-tab") .should("exist") .click({ force: true }); @@ -429,6 +453,8 @@ export class _mainPage { cy.get(".nc-meta-mgmt-metadata-tab") .should("exist") .click({ force: true }); + + cy.snip("Meta_Tab1"); } closeMetaTab() { diff --git a/scripts/cypress/support/page_objects/navigation.js b/scripts/cypress/support/page_objects/navigation.js index bf6c3893f8..67134c1629 100644 --- a/scripts/cypress/support/page_objects/navigation.js +++ b/scripts/cypress/support/page_objects/navigation.js @@ -141,6 +141,8 @@ export class _projectsPage { cy.contains("GRAPHQL APIs").closest("label").click(); } + cy.snip("XcdbCreate"); + // Submit cy.contains("button", "Create", { timeout: 20000 }).click(); @@ -211,15 +213,21 @@ export class _projectsPage { .clear() .type(cred.databaseName); + cy.snip("ExtDbCreate"); + // Test database connection cy.contains("Test Database Connection", { timeout: 20000 }).click(); + cy.snipActiveModal("Modal_OK_SaveProject"); + // Create project cy.contains("Ok & Save Project", { timeout: 20000 }).click(); // takes a while to load project this.waitHomePageLoad(); + cy.snip("Team&Auth_UserMgmt"); + return projectName; } } From 46df5e2934d1c88e82483bf761a842a0ee5c88db Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 17 Feb 2022 15:26:56 +0800 Subject: [PATCH 58/58] fix: sync changes from master to develop with ff Signed-off-by: Wing-Kam Wong --- .github/workflows/sync-to-develop.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/sync-to-develop.yml b/.github/workflows/sync-to-develop.yml index 74fa9837ec..93407111cf 100644 --- a/.github/workflows/sync-to-develop.yml +++ b/.github/workflows/sync-to-develop.yml @@ -1,4 +1,4 @@ -name: 'Sync changes back to develop branch' +name: 'Sync changes back to develop branch from master' on: # Triggered manually @@ -9,12 +9,15 @@ jobs: close-issues: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - name: Checkout + uses: actions/checkout@v1 - - name: Merge master -> develop - uses: devmasx/merge-branch@master + - name: Merge from master to develop + uses: robotology/gh-action-nightly-merge@v1.3.1 with: - type: now - from_branch: master - target_branch: develop - github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + stable_branch: 'master' + development_branch: 'develop' + allow_ff: true + allow_forks: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file