Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,38 @@
matrix:
include:
- language: generic
services:
- docker
# - language: generic
# services:
# - docker
# before_script:
# - travis/backend/build.sh
# script:
# - travis/backend/test.sh
- language: android
jdk: oraclejdk8
sudo: required
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/.android/build-cache
android:
components:
- platform-tools
- tools
- build-tools-28.0.3
- android-16
- android-28
- sys-img-armeabi-v7a-android-28
- extra-android-m2repository
- extra-google-m2repository
- extra-google-google_play_services
before_script:
- travis/backend/build.sh
- travis/frontend/build.sh
script:
- travis/backend/test.sh
- travis/frontend/test.sh

branches:
only:
Expand Down
3 changes: 3 additions & 0 deletions frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module.exports = {
browser: true,
es6: true,
node: true,
jest: true,
jasmine: true,
},
extends: [
'airbnb',
Expand All @@ -21,6 +23,7 @@ module.exports = {
},
plugins: [
'react',
'detox'
],
rules: {
"react/prop-types": ["error", { "ignore": ["navigation"] }],
Expand Down
4 changes: 4 additions & 0 deletions frontend/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
splits {
abi {
Expand Down Expand Up @@ -213,6 +215,8 @@ dependencies {
} else {
implementation jscFlavor
}
androidTestImplementation('com.wix:detox:+') { transitive = true }
androidTestImplementation 'junit:junit:4.12'
}

// Run this once to be able to run the application with BUCK
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.jobtogo;

import com.wix.detox.Detox;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.fail;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class DetoxTest {

@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);

@Test
public void runDetoxTests() {
try {
Detox.runTests(mActivityRule);
} catch (Exception e) {
fail();
}
}
}
8 changes: 7 additions & 1 deletion frontend/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

buildscript {
ext {
kotlinVersion = '1.3.10'
buildToolsVersion = "28.0.3"
minSdkVersion = 16
minSdkVersion = 18
compileSdkVersion = 28
targetSdkVersion = 28
supportLibVersion = "28.0.0"
Expand All @@ -17,6 +18,7 @@ buildscript {
dependencies {
classpath("com.android.tools.build:gradle:3.4.1")
classpath 'com.google.gms:google-services:4.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand All @@ -36,6 +38,10 @@ allprojects {
url("$rootDir/../node_modules/jsc-android/dist")
}

maven {
// All of Detox' artifacts are provided via the npm module
url "$rootDir/../node_modules/detox/Detox-android"
}
jcenter()
}
}
6 changes: 6 additions & 0 deletions frontend/e2e/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"setupFilesAfterEnv": ["./init.js"],
"testEnvironment": "node",
"reporters": ["detox/runners/jest/streamlineReporter"],
"verbose": true
}
197 changes: 197 additions & 0 deletions frontend/e2e/firstTest.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/* eslint-env detox/detox, mocha */

beforeEach(async () => {
await device.reloadReactNative();
await element(by.id('signInAuth')).tap();
element(by.id('email')).typeText('a\n');
await waitFor(element(by.id('password'))).toBeVisible().withTimeout(2000);
element(by.id('password')).typeText('a\n');
await waitFor(element(by.id('signIn'))).toBeVisible().withTimeout(2000);
await element(by.id('signIn')).tap();
});

describe('Auth Screens', () => {
it('Check AuthLanding component', async () => {
await device.reloadReactNative();
await expect(element(by.id('logoLight'))).toBeVisible();
await expect(element(by.id('jobSeeker'))).toBeVisible();
await expect(element(by.id('google'))).toBeVisible();
await expect(element(by.id('signInAuth'))).toBeVisible();

await element(by.id('signInAuth')).tap();
await expect(element(by.id('logoSignin'))).toBeVisible();
await expect(element(by.id('email'))).toBeVisible();
await expect(element(by.id('password'))).toBeVisible();
await expect(element(by.id('signIn'))).toBeVisible();
});

it('Correct login sequence', async () => {
await device.reloadReactNative();
await element(by.id('signInAuth')).tap();
await element(by.id('email')).typeText('a\n');
await element(by.id('signInAuth')).tap();
await waitFor(element(by.id('password'))).toBeVisible().withTimeout(2000);
await element(by.id('password')).typeText('a\n');
await waitFor(element(by.id('signIn'))).toBeVisible().withTimeout(2000);
await element(by.id('signIn')).tap();
await waitFor(element(by.id('jobSwipe'))).toBeVisible();
});

it('Incorrect login sequence', async () => {
await device.reloadReactNative();
await element(by.id('signInAuth')).tap();
await element(by.id('email')).typeText('\n');
await waitFor(element(by.id('password'))).toBeVisible().withTimeout(2000);
await element(by.id('password')).typeText('\n');
await waitFor(element(by.id('signIn'))).toBeVisible().withTimeout(2000);
// await element(by.id('signIn')).tap();
await expect(element(by.id('loginErrorMsg'))).toBeVisible();
// TODO: test for difference error responses
});
});

describe('Home Screen', () => {
it('Check Jobswipe components', async () => {
await expect(element(by.id('mainHeader'))).toBeVisible();
await expect(element(by.id('inbox'))).toBeVisible();
// Check the inbox model
await element(by.id('inbox')).tap();
await expect(element(by.id('mainHeader'))).toBeVisible();
await expect(element(by.id('infoDisplay'))).toBeVisible();

// Switch back from the inbox model
await element(by.id('inbox')).tap();
await expect(element(by.id('mainHeader'))).toBeVisible();
});

it('Check share modal', async () => {
// Check the share job modal
await element(by.id('card0')).tap();
await expect(element(by.id('shareModal'))).toBeVisible();

// Close the share job modal
await element(by.id('closeShare')).tap();
await expect(element(by.id('shareModal'))).toBeNotVisible();
await expect(element(by.id('mainHeader'))).toBeVisible();
});

it('Check info modal', async () => {
// Check the share job modal
await element(by.id('card0Open')).tap();
await waitFor(element(by.id('card0Description'))).toBeVisible().withTimeout(2000);
await expect(element(by.id('card0Description'))).toBeVisible();

// Close the share job modal
await element(by.id('card0Close')).tap();
await expect(element(by.id('card0Description'))).toBeNotVisible();
});
});

describe('Liked Screen', () => {
it('Check Liked components', async () => {
await element(by.id('liked')).tap();
await expect(element(by.id('navHeaderLiked'))).toBeVisible();
await expect(element(by.id('search'))).toBeVisible();
await expect(element(by.id('user'))).toBeVisible();
await expect(element(by.text('Liked Jobs'))).toBeVisible();

await expect(element(by.id('sendJobs'))).toBeVisible();
await expect(element(by.id('likedJobs'))).toBeVisible();
await expect(element(by.id('jobItem0'))).toBeVisible();
});
});

describe('Friends Screen', () => {
it('Check Friends components', async () => {
await element(by.id('friends')).tap();

// Nav header
await expect(element(by.id('navHeaderFriends'))).toBeVisible();
await expect(element(by.id('search'))).toBeVisible();
await expect(element(by.id('user'))).toBeVisible();

// Switch navigator
await expect(element(by.id('switchNav'))).toBeVisible();
await expect(element(by.id('switchNavOption1'))).toBeVisible();
await expect(element(by.id('switchNavOption2'))).toBeVisible();
await expect(element(by.text('Pending Friends'))).toBeVisible();
await expect(element(by.text('Your Friends'))).toBeVisible();

// User should have no pending friends
await expect(element(by.id('infoDisplay'))).toBeVisible();
});

it('Navigate between Pending/Your Friends', async () => {
await element(by.id('friends')).tap();
await element(by.id('switchNavOption2')).tap();
await element(by.id('switchNavOption1')).tap();

// xfail once friends are added to user
await expect(element(by.id('infoDisplay'))).toBeVisible();
});

it('Display 100 friends', async () => {
const NON_FUNC_REQ_FRIEND_COUNT = 100;
await element(by.id('friends')).tap();
await element(by.id('switchNavOption2')).tap();
const userNums = Array.from(Array(NON_FUNC_REQ_FRIEND_COUNT).keys());

await Promise.all(userNums.map(async num => {
await waitFor(element(by.id(`userItem${num}`)))
.toBeVisible().whileElement(by.id('userList')).scroll(300, 'down');
}));
});

it('Check user search component', async () => {
await element(by.id('friends')).tap();
await element(by.id('search')).tap();
await expect(element(by.id('searchBack'))).toBeVisible();
await expect(element(by.id('searchInput'))).toBeVisible();
});

it('Users search sequence', async () => {
await element(by.id('friends')).tap();
await element(by.id('search')).tap();

await expect(element(by.id('userList'))).toBeNotVisible();

element(by.id('searchInput')).typeText('search query\n');
await element(by.id('searchBack')).tap();

await expect(element(by.id('userList'))).toBeVisible();

// Go back to previous screen
await expect(element(by.id('editFriends'))).toBeVisible();
});
});

describe('Resume Page', () => {
it('Check resume components', async () => {
await element(by.id('resume')).tap();
await expect(element(by.id('navHeaderSkills'))).toBeVisible();
await expect(element(by.id('textSkills'))).toBeVisible();
await expect(element(by.id('checkingDoc'))).toBeVisible();
await expect(element(by.id('uploadResume'))).toBeVisible();
// await element(by.id('uploadResume')).tap();
// todo
});
});

describe('Navigation', () => {
it('Navigation between pages', async () => {
// Check navigation buttons
await expect(element(by.id('home'))).toBeVisible();
await expect(element(by.id('liked'))).toBeVisible();
await expect(element(by.id('friends'))).toBeVisible();
await expect(element(by.id('resume'))).toBeVisible();

await element(by.id('friends')).tap();
await expect(element(by.id('editFriends'))).toBeVisible();
await element(by.id('resume')).tap();
await expect(element(by.id('editSkills'))).toBeVisible();
await element(by.id('home')).tap();
await expect(element(by.id('jobSwipe'))).toBeVisible();
await element(by.id('liked')).tap();
await expect(element(by.id('sendLikedJobs'))).toBeVisible();
});
});
27 changes: 27 additions & 0 deletions frontend/e2e/init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* eslint-env detox/detox, mocha */

/* eslint-disable import/no-extraneous-dependencies */
import detox from 'detox';
import adapter from 'detox/runners/jest/adapter';
import specReporter from 'detox/runners/jest/specReporter';
import packageConfig from '../package.json';

const config = packageConfig.detox;

// Set the default timeout
jest.setTimeout(120000);
jasmine.getEnv().addReporter(adapter);
jasmine.getEnv().addReporter(specReporter);

beforeAll(async () => {
await detox.init(config);
});

beforeEach(async () => {
await adapter.beforeEach();
});

afterAll(async () => {
await adapter.afterAll();
await detox.cleanup();
});
Loading