[REGRESSION] Auth via deep linking not working (#3015)
* Update rocketchat and add e2e test for deep linking * Update rocketchat and add e2e test for deep linking * Update deeplinking e2e * fix deep linking auth * Test deep linking auth * Fix deeplink to rid and add tests * Small refactor * Add non existing server test Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
parent
25b71155e6
commit
c5bf13c22d
|
@ -15,6 +15,7 @@ import {
|
||||||
} from '../actions/app';
|
} from '../actions/app';
|
||||||
import { localAuthenticate } from '../utils/localAuthentication';
|
import { localAuthenticate } from '../utils/localAuthentication';
|
||||||
import { goRoom } from '../utils/goRoom';
|
import { goRoom } from '../utils/goRoom';
|
||||||
|
import { loginRequest } from '../actions/login';
|
||||||
|
|
||||||
const roomTypes = {
|
const roomTypes = {
|
||||||
channel: 'c', direct: 'd', group: 'p', channels: 'l'
|
channel: 'c', direct: 'd', group: 'p', channels: 'l'
|
||||||
|
@ -41,9 +42,13 @@ const popToRoot = function popToRoot({ isMasterDetail }) {
|
||||||
|
|
||||||
const navigate = function* navigate({ params }) {
|
const navigate = function* navigate({ params }) {
|
||||||
yield put(appStart({ root: ROOT_INSIDE }));
|
yield put(appStart({ root: ROOT_INSIDE }));
|
||||||
if (params.path) {
|
if (params.path || params.rid) {
|
||||||
const [type, name] = params.path.split('/');
|
let type;
|
||||||
if (type !== 'invite') {
|
let name;
|
||||||
|
if (params.path) {
|
||||||
|
[type, name] = params.path.split('/');
|
||||||
|
}
|
||||||
|
if (type !== 'invite' || params.rid) {
|
||||||
const room = yield RocketChat.canOpenRoom(params);
|
const room = yield RocketChat.canOpenRoom(params);
|
||||||
if (room) {
|
if (room) {
|
||||||
const item = {
|
const item = {
|
||||||
|
@ -110,7 +115,11 @@ const handleOpen = function* handleOpen({ params }) {
|
||||||
|
|
||||||
// If there's host, continue
|
// If there's host, continue
|
||||||
if (!/^(http|https)/.test(host)) {
|
if (!/^(http|https)/.test(host)) {
|
||||||
host = `https://${ host }`;
|
if (/^localhost(:\d+)?/.test(host)) {
|
||||||
|
host = `http://${ host }`;
|
||||||
|
} else {
|
||||||
|
host = `https://${ host }`;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Notification should always come from https
|
// Notification should always come from https
|
||||||
host = host.replace('http://', 'https://');
|
host = host.replace('http://', 'https://');
|
||||||
|
@ -163,7 +172,7 @@ const handleOpen = function* handleOpen({ params }) {
|
||||||
|
|
||||||
if (params.token) {
|
if (params.token) {
|
||||||
yield take(types.SERVER.SELECT_SUCCESS);
|
yield take(types.SERVER.SELECT_SUCCESS);
|
||||||
yield RocketChat.connect({ server: host, user: { token: params.token } });
|
yield put(loginRequest({ resume: params.token }, true));
|
||||||
yield take(types.LOGIN.SUCCESS);
|
yield take(types.LOGIN.SUCCESS);
|
||||||
yield navigate({ params });
|
yield navigate({ params });
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const random = require('./helpers/random');
|
const random = require('./helpers/random');
|
||||||
const value = random(20);
|
const value = random(20);
|
||||||
const data = {
|
const data = {
|
||||||
server: 'http://127.0.0.1:3000',
|
server: 'http://localhost:3000',
|
||||||
adminUser: 'admin',
|
adminUser: 'admin',
|
||||||
adminPassword: 'password',
|
adminPassword: 'password',
|
||||||
alternateServer: 'https://stable.rocket.chat',
|
alternateServer: 'https://stable.rocket.chat',
|
||||||
|
|
|
@ -3,30 +3,29 @@ const {
|
||||||
} = require('detox');
|
} = require('detox');
|
||||||
const data = require('../data');
|
const data = require('../data');
|
||||||
|
|
||||||
async function navigateToWorkspace() {
|
async function navigateToWorkspace(server = data.server) {
|
||||||
await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(10000);
|
await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(10000);
|
||||||
await element(by.id('join-workspace')).tap();
|
await element(by.id('join-workspace')).tap();
|
||||||
await waitFor(element(by.id('new-server-view'))).toBeVisible().withTimeout(60000);
|
await waitFor(element(by.id('new-server-view'))).toBeVisible().withTimeout(60000);
|
||||||
await element(by.id('new-server-view-input')).replaceText(data.server);
|
await element(by.id('new-server-view-input')).replaceText(server);
|
||||||
await element(by.id('new-server-view-button')).tap();
|
await element(by.id('new-server-view-button')).tap();
|
||||||
await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(60000);
|
await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(60000);
|
||||||
await expect(element(by.id('workspace-view'))).toBeVisible();
|
await expect(element(by.id('workspace-view'))).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function navigateToLogin() {
|
async function navigateToLogin(server) {
|
||||||
await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000);
|
await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000);
|
||||||
await navigateToWorkspace();
|
await navigateToWorkspace(server);
|
||||||
await element(by.id('workspace-view-login')).tap();
|
await element(by.id('workspace-view-login')).tap();
|
||||||
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('login-view'))).toBeVisible();
|
await expect(element(by.id('login-view'))).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function navigateToRegister() {
|
async function navigateToRegister(server) {
|
||||||
await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000);
|
await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000);
|
||||||
await navigateToWorkspace();
|
await navigateToWorkspace(server);
|
||||||
await element(by.id('workspace-view-register')).tap();
|
await element(by.id('workspace-view-register')).tap();
|
||||||
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('register-view'))).toBeVisible();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function login(username, password) {
|
async function login(username, password) {
|
||||||
|
@ -120,6 +119,14 @@ async function tryTapping(theElement, timeout, longtap = false){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkServer = async(server) => {
|
||||||
|
const label = `Connected to ${ server }`;
|
||||||
|
await element(by.id('rooms-list-view-sidebar')).tap();
|
||||||
|
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
|
||||||
|
await waitFor(element(by.label(label))).toBeVisible().withTimeout(10000);
|
||||||
|
await element(by.id('sidebar-close-drawer')).tap();
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
navigateToWorkspace,
|
navigateToWorkspace,
|
||||||
navigateToLogin,
|
navigateToLogin,
|
||||||
|
@ -133,5 +140,6 @@ module.exports = {
|
||||||
tapBack,
|
tapBack,
|
||||||
sleep,
|
sleep,
|
||||||
searchRoom,
|
searchRoom,
|
||||||
tryTapping
|
tryTapping,
|
||||||
|
checkServer
|
||||||
};
|
};
|
|
@ -135,6 +135,16 @@ const setup = async () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const get = (endpoint) => {
|
||||||
|
console.log(`GET /${ endpoint }`)
|
||||||
|
return rocketchat.get(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
const post = (endpoint, body) => {
|
||||||
|
console.log(`POST /${ endpoint } ${ JSON.stringify(body) }`)
|
||||||
|
return rocketchat.post(endpoint, body);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
setup, sendMessage
|
setup, sendMessage, get, post
|
||||||
}
|
}
|
|
@ -2,15 +2,7 @@ const {
|
||||||
device, expect, element, by, waitFor
|
device, expect, element, by, waitFor
|
||||||
} = require('detox');
|
} = require('detox');
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { sleep, navigateToLogin, login } = require('../../helpers/app');
|
const { navigateToLogin, login, checkServer } = require('../../helpers/app');
|
||||||
|
|
||||||
const checkServer = async(server) => {
|
|
||||||
const label = `Connected to ${ server }`;
|
|
||||||
await element(by.id('rooms-list-view-sidebar')).tap();
|
|
||||||
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
|
|
||||||
await waitFor(element(by.label(label))).toBeVisible().withTimeout(60000);
|
|
||||||
await element(by.id('sidebar-close-drawer')).tap();
|
|
||||||
}
|
|
||||||
|
|
||||||
const reopenAndCheckServer = async(server) => {
|
const reopenAndCheckServer = async(server) => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' } });
|
await device.launchApp({ permissions: { notifications: 'YES' } });
|
||||||
|
|
|
@ -2,15 +2,7 @@ const {
|
||||||
device, element, by, waitFor
|
device, element, by, waitFor
|
||||||
} = require('detox');
|
} = require('detox');
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { sleep, navigateToLogin, login } = require('../../helpers/app');
|
const { sleep, navigateToLogin, login, checkServer } = require('../../helpers/app');
|
||||||
|
|
||||||
const checkServer = async(server) => {
|
|
||||||
const label = `Connected to ${ server }`;
|
|
||||||
await element(by.id('rooms-list-view-sidebar')).tap();
|
|
||||||
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
|
|
||||||
await waitFor(element(by.label(label))).toBeVisible().withTimeout(10000);
|
|
||||||
await element(by.id('sidebar-close-drawer')).tap();
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Delete server', () => {
|
describe('Delete server', () => {
|
||||||
before(async() => {
|
before(async() => {
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
const {
|
||||||
|
device, element, by, waitFor
|
||||||
|
} = require('detox');
|
||||||
|
const data = require('../../data');
|
||||||
|
const { tapBack, checkServer, navigateToRegister, login } = require('../../helpers/app');
|
||||||
|
const { post, get } = require('../../helpers/data_setup');
|
||||||
|
|
||||||
|
const DEEPLINK_METHODS = { AUTH: 'auth', ROOM: 'room' };
|
||||||
|
const getDeepLink = (method, server, params) => {
|
||||||
|
const deeplink = `rocketchat://${ method }?host=${ server.replace(/^(http:\/\/|https:\/\/)/, '') }&${params}`;
|
||||||
|
console.log(`Deeplinking to: ${ deeplink }`);
|
||||||
|
return deeplink;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Deep linking', () => {
|
||||||
|
let userId;
|
||||||
|
let token;
|
||||||
|
before(async() => {
|
||||||
|
const loginResult = await post('login', {
|
||||||
|
user: data.users.regular.username,
|
||||||
|
password: data.users.regular.password
|
||||||
|
})
|
||||||
|
userId = loginResult.data.data.userId
|
||||||
|
token = loginResult.data.data.authToken
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Authentication', () => {
|
||||||
|
it('should run a deep link to an invalid account and raise error', async() => {
|
||||||
|
await device.launchApp({
|
||||||
|
permissions: { notifications: 'YES' },
|
||||||
|
newInstance: true,
|
||||||
|
url: getDeepLink(DEEPLINK_METHODS.AUTH, data.server, 'userId=123&token=abc'),
|
||||||
|
sourceApp: 'com.apple.mobilesafari'
|
||||||
|
});
|
||||||
|
await waitFor(element(by.text('You\'ve been logged out by the server. Please log in again.'))).toExist().withTimeout(5000); // TODO: we need to improve this message
|
||||||
|
});
|
||||||
|
|
||||||
|
const authAndNavigate = async() => {
|
||||||
|
await device.launchApp({
|
||||||
|
permissions: { notifications: 'YES' },
|
||||||
|
newInstance: true,
|
||||||
|
url: getDeepLink(DEEPLINK_METHODS.AUTH, data.server, `userId=${ userId }&token=${ token }&path=group/${ data.groups.private.name }`),
|
||||||
|
sourceApp: 'com.apple.mobilesafari'
|
||||||
|
});
|
||||||
|
await waitFor(element(by.id(`room-view-title-${ data.groups.private.name }`))).toExist().withTimeout(10000);
|
||||||
|
await tapBack();
|
||||||
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||||
|
await checkServer(data.server);
|
||||||
|
await waitFor(element(by.id(`rooms-list-view-item-${ data.groups.private.name }`))).toBeVisible().withTimeout(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should authenticate and navigate', async() => {
|
||||||
|
await authAndNavigate();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should authenticate while logged in another server', async() => {
|
||||||
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
await navigateToRegister(data.alternateServer);
|
||||||
|
await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
|
||||||
|
await element(by.id('register-view-username')).replaceText(data.registeringUser.username);
|
||||||
|
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
|
||||||
|
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
||||||
|
await element(by.id('register-view-submit')).tap();
|
||||||
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||||
|
await authAndNavigate();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Room', () => {
|
||||||
|
describe('While logged in', async() => {
|
||||||
|
it('should navigate to the room using path', async() => {
|
||||||
|
await device.launchApp({
|
||||||
|
permissions: { notifications: 'YES' },
|
||||||
|
newInstance: true,
|
||||||
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${ data.groups.private.name }`),
|
||||||
|
sourceApp: 'com.apple.mobilesafari'
|
||||||
|
});
|
||||||
|
await waitFor(element(by.id(`room-view-title-${ data.groups.private.name }`))).toExist().withTimeout(10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate to the room using rid', async() => {
|
||||||
|
const roomResult = await get(`groups.info?roomName=${ data.groups.private.name }`)
|
||||||
|
await device.launchApp({
|
||||||
|
permissions: { notifications: 'YES' },
|
||||||
|
newInstance: true,
|
||||||
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `rid=${ roomResult.data.group._id }`),
|
||||||
|
sourceApp: 'com.apple.mobilesafari'
|
||||||
|
});
|
||||||
|
await waitFor(element(by.id(`room-view-title-${ data.groups.private.name }`))).toExist().withTimeout(10000);
|
||||||
|
await tapBack();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Others', async() => {
|
||||||
|
it('should change server', async() => {
|
||||||
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
|
await element(by.id('rooms-list-header-server-dropdown-button')).tap();
|
||||||
|
await waitFor(element(by.id('rooms-list-header-server-dropdown'))).toBeVisible().withTimeout(5000);
|
||||||
|
await element(by.id(`rooms-list-header-server-${ data.alternateServer }`)).tap();
|
||||||
|
await checkServer(data.alternateServer);
|
||||||
|
|
||||||
|
await device.launchApp({
|
||||||
|
permissions: { notifications: 'YES' },
|
||||||
|
newInstance: true,
|
||||||
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${ data.groups.private.name }`),
|
||||||
|
sourceApp: 'com.apple.mobilesafari'
|
||||||
|
});
|
||||||
|
await waitFor(element(by.id(`room-view-title-${ data.groups.private.name }`))).toExist().withTimeout(10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add a not existing server and fallback to the previous one', async() => {
|
||||||
|
await device.launchApp({
|
||||||
|
permissions: { notifications: 'YES' },
|
||||||
|
newInstance: true,
|
||||||
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, 'https://google.com'),
|
||||||
|
sourceApp: 'com.apple.mobilesafari'
|
||||||
|
});
|
||||||
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||||
|
await checkServer(data.server);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue