Repository: akvo/akvo-rsr

Issue:
End-to-end testing



Discussion:

Resolving patch:
diff --git a/akvo/rsr/management/commands/populate_e2e_data.py b/akvo/rsr/management/commands/populate_e2e_data.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/management/commands/populate_e2e_data.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+
+# Akvo Reporting is covered by the GNU Affero General Public License.
+# See more details in the license.txt file located at the root folder of the Akvo RSR module.
+# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+
+import logging
+from django.conf import settings
+from django.core.management.base import BaseCommand
+from django.contrib.auth.models import Group
+from akvo.rsr.models import User, Organisation, Employment
+
+
+def create_user(email, password, is_admin=False, is_staff=False, is_superuser=False, is_active=True):
+    first_name = email.split('@')[0]
+    last_name = 'von {}enstein'.format(first_name)
+    user = User.objects.create(
+        email=email,
+        username=email,
+        first_name=first_name,
+        last_name=last_name,
+        is_staff=is_staff,
+        is_admin=is_admin,
+        is_superuser=is_superuser,
+        is_active=is_active,
+    )
+    user.set_password(password)
+    user.save()
+    return user
+
+
+def create_organisation(name, can_create_projects=True):
+    org = Organisation.objects.create(
+        name=name, long_name=name, can_create_projects=can_create_projects
+    )
+    return org
+
+
+def make_employment(user, org, group_name):
+    group = Group.objects.get(name=group_name)
+    return Employment.objects.create(user=user, organisation=org, group=group, is_approved=True)
+
+
+class Command(BaseCommand):
+
+    def add_arguments(self, parser):
+        parser.add_argument('--teardown', action='store_true', help="Teardown data")
+
+    def handle(self, *args, **options):
+        teardown = bool(options['teardown'])
+        verbosity = int(options['verbosity'])
+        if verbosity < 2:
+            logging.disable(logging.INFO)
+        self.clean()
+        if not teardown:
+            self.populate()
+        if verbosity < 2:
+            logging.disable(logging.NOTSET)
+
+    def populate(self):
+        saved_email_backend = settings.EMAIL_BACKEND
+        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
+
+        create_user('e2e-admin@akvo.org', 'password', is_staff=True, is_superuser=True)
+        user = create_user('e2e-user@akvo.org', 'password')
+        org = create_organisation('e2e-org')
+        make_employment(user, org, 'Admins')
+
+        settings.EMAIL_BACKEND = saved_email_backend
+
+    def clean(self):
+        if Organisation.objects.filter(name='e2e-org').count():
+            org = Organisation.objects.get(name='e2e-org')
+            org.projects.all().delete()
+            org.delete()
+        User.objects.filter(email__in=['e2e-admin@akvo.org', 'e2e-user@akvo.org']).delete()


Test patch:
diff --git a/akvo/rsr/e2e/tests/create-project.test.js b/akvo/rsr/e2e/tests/create-project.test.js
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/e2e/tests/create-project.test.js
@@ -0,0 +1,22 @@
+import {loginAsDefaultUser, myProjectsPage, projectEditorPage, isAtPage} from '../pages'
+import faker from '@faker-js/faker'
+
+describe('Create project feature', () => {
+  beforeAll(async () => {
+    await loginAsDefaultUser(myProjectsPage)
+  })
+
+  it('should redirect to Project editor page', async () => {
+    await myProjectsPage.addNewProject()
+    expect(await isAtPage(projectEditorPage)).toBe(true)
+  })
+
+  it('should be able to create project', async () => {
+    const title = faker.company.catchPhrase()
+    const subtitle = faker.company.bs()
+    await projectEditorPage.setProjectInfo({title, subtitle})
+    await myProjectsPage.visit()
+    expect(await myProjectsPage.contains(title)).toBe(true)
+    expect(await myProjectsPage.contains(subtitle)).toBe(true)
+  })
+})
diff --git a/akvo/rsr/e2e/tests/login.test.js b/akvo/rsr/e2e/tests/login.test.js
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/e2e/tests/login.test.js
@@ -0,0 +1,18 @@
+import {loginPage, myProjectsPage, ensureLoggedOut, isAtPage, isLoggedIn} from '../pages'
+
+describe('Login page', () => {
+  beforeEach(async () => {
+    await ensureLoggedOut()
+    await loginPage.visit()
+  })
+
+  test('registered user can login', async () => {
+    await loginPage.login('e2e-user@akvo.org', 'password')
+    expect(await isLoggedIn()).toBe(true)
+  });
+
+  it('should redirect to "My projects" page', async () => {
+    await loginPage.login('e2e-user@akvo.org', 'password')
+    expect(await isAtPage(myProjectsPage)).toBe(true)
+  })
+})
diff --git a/akvo/rsr/e2e/tests/smoke.test.js b/akvo/rsr/e2e/tests/smoke.test.js
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/e2e/tests/smoke.test.js
@@ -0,0 +1,13 @@
+import {landingPage, ensureLoggedOut} from '../pages'
+
+describe('Project directory', () => {
+  beforeEach(async () => {
+    await ensureLoggedOut()
+    await landingPage.visit()
+  })
+
+  it('should display "Most active project" text on page', async () => {
+    const haveText = await landingPage.contains('Most active projects')
+    expect(haveText).toBe(true)
+  })
+})