Lint and incremental
This commit is contained in:
parent
047d4e5889
commit
0182c0efd2
|
@ -1,8 +1,5 @@
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const { device } = require('detox');
|
const { device } = require('detox');
|
||||||
const { sleep } = require('./app');
|
|
||||||
|
|
||||||
const defaultLaunchArgs = { permissions: { notifications: 'YES' } };
|
|
||||||
|
|
||||||
function runCommand(command) {
|
function runCommand(command) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -26,27 +23,6 @@ exports.prepareAndroid = async() => {
|
||||||
await runCommand('adb shell settings put secure autofill_service null');
|
await runCommand('adb shell settings put secure autofill_service null');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.launchWithLanguage = async(language, countryCode = 'US', launchArgs = defaultLaunchArgs) => {
|
|
||||||
if (device.id === undefined) {
|
|
||||||
await device.launchApp(launchArgs);
|
|
||||||
}
|
|
||||||
if (device.getPlatform() === 'android') {
|
|
||||||
await runCommand('adb root');
|
|
||||||
await runCommand(`adb shell "setprop persist.sys.locale ${ language }-${ countryCode }; setprop ctl.restart zygote"`);
|
|
||||||
await sleep(20000);
|
|
||||||
await device.launchApp(launchArgs);
|
|
||||||
} else {
|
|
||||||
const langLocale = typeof countryCode === 'string' ? `${ language }-${ countryCode }` : language;
|
|
||||||
await device.launchApp({
|
|
||||||
...launchArgs,
|
|
||||||
languageAndLocale: {
|
|
||||||
language: langLocale,
|
|
||||||
locale: langLocale
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.closeKeyboardAndroid = async() => {
|
exports.closeKeyboardAndroid = async() => {
|
||||||
await device.pressBack(); // Android-only
|
await device.pressBack(); // Android-only
|
||||||
};
|
};
|
||||||
|
|
|
@ -200,7 +200,8 @@ describe('E2E Encryption', () => {
|
||||||
await element(by.id('e2e-encryption-security-view-reset-key').and(by.label('Reset E2E Key'))).tap();
|
await element(by.id('e2e-encryption-security-view-reset-key').and(by.label('Reset E2E Key'))).tap();
|
||||||
await waitFor(element(by.text('Are you sure?'))).toExist().withTimeout(2000);
|
await waitFor(element(by.text('Are you sure?'))).toExist().withTimeout(2000);
|
||||||
await expect(element(by.text('You\'re going to be logged out.'))).toExist();
|
await expect(element(by.text('You\'re going to be logged out.'))).toExist();
|
||||||
await element(by.label('Yes, reset it').and(by.type(alertButtonType))).tap();
|
await element(by.text('Yes, reset it').and(by.type(alertButtonType))).tap();
|
||||||
|
await element(by.text('OK').and(by.type(alertButtonType))).tap();
|
||||||
await sleep(2000);
|
await sleep(2000);
|
||||||
await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(10000);
|
await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(10000);
|
||||||
await element(by.id('workspace-view-login')).tap();
|
await element(by.id('workspace-view-login')).tap();
|
||||||
|
|
|
@ -77,7 +77,7 @@ describe('i18n', () => {
|
||||||
|
|
||||||
describe('Rocket.Chat language', () => {
|
describe('Rocket.Chat language', () => {
|
||||||
before(async() => {
|
before(async() => {
|
||||||
await device.launchApp({ ...defaultLaunchArgs, newInstance: true });
|
await device.launchApp({ ...defaultLaunchArgs, delete: true });
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(testuser.username, testuser.password);
|
await login(testuser.username, testuser.password);
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,7 +29,8 @@ describe('Server history', () => {
|
||||||
|
|
||||||
it('should tap on a server history and navigate to login', async() => {
|
it('should tap on a server history and navigate to login', async() => {
|
||||||
await element(by.id(`server-history-${ data.server }`)).tap();
|
await element(by.id(`server-history-${ data.server }`)).tap();
|
||||||
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(5000);
|
// Detox synchronization breaks at this point. Look into this
|
||||||
|
await waitFor(element(by.id('login-view-email'))).toBeVisible().withTimeout(5000);
|
||||||
await expect(element(by.text(data.users.regular.username).withAncestor(by.id('login-view-email'))));
|
await expect(element(by.text(data.users.regular.username).withAncestor(by.id('login-view-email'))));
|
||||||
// await expect(element(by.id('login-view-email'))).toHaveText(data.users.regular.username);
|
// await expect(element(by.id('login-view-email'))).toHaveText(data.users.regular.username);
|
||||||
});
|
});
|
||||||
|
|
|
@ -226,7 +226,7 @@ describe('Room actions screen', () => {
|
||||||
await element(by.text(`${ data.random }messageToStar`)).atIndex(0).longPress();
|
await element(by.text(`${ data.random }messageToStar`)).atIndex(0).longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await expect(element(by.id('action-sheet'))).toExist();
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.text('Unstar')).atIndex(0).tap();
|
await element(by.label('Unstar')).atIndex(0).tap();
|
||||||
|
|
||||||
await waitFor(element(by.text(`${ data.random }messageToStar`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible().withTimeout(60000);
|
await waitFor(element(by.text(`${ data.random }messageToStar`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible().withTimeout(60000);
|
||||||
await backToActions();
|
await backToActions();
|
||||||
|
@ -252,7 +252,7 @@ describe('Room actions screen', () => {
|
||||||
|
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await expect(element(by.id('action-sheet'))).toExist();
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.text('Unpin')).atIndex(0).tap();
|
await element(by.label('Unpin')).atIndex(0).tap();
|
||||||
|
|
||||||
await waitFor(element(by.text(`${ data.random }messageToPin`).withAncestor(by.id('pinned-messages-view')))).not.toExist().withTimeout(6000);
|
await waitFor(element(by.text(`${ data.random }messageToPin`).withAncestor(by.id('pinned-messages-view')))).not.toExist().withTimeout(6000);
|
||||||
await backToActions();
|
await backToActions();
|
||||||
|
@ -402,7 +402,7 @@ describe('Room actions screen', () => {
|
||||||
|
|
||||||
it('should remove user from room', async() => {
|
it('should remove user from room', async() => {
|
||||||
await openActionSheet('rocket.cat');
|
await openActionSheet('rocket.cat');
|
||||||
await element(by.text('Remove from room')).tap();
|
await element(by.label('Remove from room')).tap();
|
||||||
await waitFor(element(by.text('Are you sure?'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('Are you sure?'))).toExist().withTimeout(5000);
|
||||||
await element(by.text('Yes, remove user!').and(by.type(alertButtonType))).tap();
|
await element(by.text('Yes, remove user!').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('room-members-view-item-rocket.cat'))).toBeNotVisible().withTimeout(60000);
|
await waitFor(element(by.id('room-members-view-item-rocket.cat'))).toBeNotVisible().withTimeout(60000);
|
||||||
|
@ -461,20 +461,20 @@ describe('Room actions screen', () => {
|
||||||
|
|
||||||
it('should set/remove as mute', async() => {
|
it('should set/remove as mute', async() => {
|
||||||
await openActionSheet(user.username);
|
await openActionSheet(user.username);
|
||||||
await element(by.text('Mute')).tap();
|
await element(by.label('Mute')).tap();
|
||||||
await waitFor(element(by.text('Are you sure?'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('Are you sure?'))).toExist().withTimeout(5000);
|
||||||
await element(by.text('Mute').and(by.type(alertButtonType))).tap();
|
await element(by.text('Mute').and(by.type(alertButtonType))).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
|
|
||||||
await openActionSheet(user.username);
|
await openActionSheet(user.username);
|
||||||
await element(by.text('Unmute')).tap();
|
await element(by.label('Unmute')).tap();
|
||||||
await waitFor(element(by.text('Are you sure?'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('Are you sure?'))).toExist().withTimeout(5000);
|
||||||
await element(by.text('Unmute').and(by.type(alertButtonType))).tap();
|
await element(by.text('Unmute').and(by.type(alertButtonType))).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
|
|
||||||
await openActionSheet(user.username);
|
await openActionSheet(user.username);
|
||||||
// Tests if Remove as mute worked
|
// Tests if Remove as mute worked
|
||||||
await waitFor(element(by.text('Mute'))).toExist().withTimeout(5000);
|
await waitFor(element(by.label('Mute'))).toExist().withTimeout(5000);
|
||||||
await closeActionSheet();
|
await closeActionSheet();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -520,9 +520,9 @@ describe('Room actions screen', () => {
|
||||||
await element(by.id('room-actions-scrollview')).scrollTo('bottom');
|
await element(by.id('room-actions-scrollview')).scrollTo('bottom');
|
||||||
await waitFor(element(by.id('room-actions-block-user'))).toExist();
|
await waitFor(element(by.id('room-actions-block-user'))).toExist();
|
||||||
await element(by.id('room-actions-block-user')).tap();
|
await element(by.id('room-actions-block-user')).tap();
|
||||||
await waitFor(element(by.text('Unblock user'))).toExist().withTimeout(60000);
|
await waitFor(element(by.label('Unblock user'))).toExist().withTimeout(60000);
|
||||||
await element(by.id('room-actions-block-user')).tap();
|
await element(by.id('room-actions-block-user')).tap();
|
||||||
await waitFor(element(by.text('Block user'))).toExist().withTimeout(60000);
|
await waitFor(element(by.label('Block user'))).toExist().withTimeout(60000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,9 +28,9 @@ describe('Mark as unread', () => {
|
||||||
const message = `${ data.random }message-mark-as-unread`;
|
const message = `${ data.random }message-mark-as-unread`;
|
||||||
const channelName = `@${ data.users.regular.username }`;
|
const channelName = `@${ data.users.regular.username }`;
|
||||||
await sendMessage(data.users.alternate, channelName, message);
|
await sendMessage(data.users.alternate, channelName, message);
|
||||||
await waitFor(element(by.label(message)).atIndex(0)).toExist().withTimeout(30000);
|
await waitFor(element(by.text(message)).atIndex(0)).toExist().withTimeout(30000);
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
await element(by.label(message)).atIndex(0).longPress();
|
await element(by.text(message)).atIndex(0).longPress();
|
||||||
await waitFor(element(by.id('action-sheet-handle'))).toBeVisible().withTimeout(3000);
|
await waitFor(element(by.id('action-sheet-handle'))).toBeVisible().withTimeout(3000);
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.label('Mark Unread')).atIndex(0).tap();
|
await element(by.label('Mark Unread')).atIndex(0).tap();
|
||||||
|
|
|
@ -40,29 +40,29 @@ describe('Room', () => {
|
||||||
|
|
||||||
it('should jump to an old message and load its surroundings', async() => {
|
it('should jump to an old message and load its surroundings', async() => {
|
||||||
await navigateToRoom('jumping');
|
await navigateToRoom('jumping');
|
||||||
await waitFor(element(by.label('Quote first message'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('Quote first message'))).toExist().withTimeout(5000);
|
||||||
await element(by.label('1')).atIndex(0).tap();
|
await element(by.text('1')).atIndex(0).tap();
|
||||||
await waitForLoading();
|
await waitForLoading();
|
||||||
await expect(element(by.label('1')).atIndex(0)).toExist();
|
await expect(element(by.text('1')).atIndex(0)).toExist();
|
||||||
await expect(element(by.label('2'))).toExist();
|
await expect(element(by.text('2'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should tap FAB and scroll to bottom', async() => {
|
it('should tap FAB and scroll to bottom', async() => {
|
||||||
await waitFor(element(by.id('nav-jump-to-bottom'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('nav-jump-to-bottom'))).toExist().withTimeout(5000);
|
||||||
await element(by.id('nav-jump-to-bottom')).tap();
|
await element(by.id('nav-jump-to-bottom')).tap();
|
||||||
await waitFor(element(by.label('Quote first message'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('Quote first message'))).toExist().withTimeout(5000);
|
||||||
await clearCache();
|
await clearCache();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load messages on scroll', async() => {
|
it('should load messages on scroll', async() => {
|
||||||
await navigateToRoom('jumping');
|
await navigateToRoom('jumping');
|
||||||
await waitFor(element(by.id('room-view-messages'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('room-view-messages'))).toExist().withTimeout(5000);
|
||||||
await waitFor(element(by.label('300'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('300'))).toExist().withTimeout(5000);
|
||||||
let found = false;
|
let found = false;
|
||||||
while (!found) {
|
while (!found) {
|
||||||
await element(by.id('room-view-messages')).atIndex(0).scroll(500, 'up');
|
await element(by.id('room-view-messages')).atIndex(0).scroll(500, 'up');
|
||||||
try {
|
try {
|
||||||
await expect(element(by.label('249'))).toExist();
|
await expect(element(by.text('249'))).toExist();
|
||||||
found = true;
|
found = true;
|
||||||
} catch {
|
} catch {
|
||||||
//
|
//
|
||||||
|
@ -76,68 +76,68 @@ describe('Room', () => {
|
||||||
await element(by.id('room-view-search')).tap();
|
await element(by.id('room-view-search')).tap();
|
||||||
await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(5000);
|
||||||
await element(by.id('search-message-view-input')).typeText('30\n');
|
await element(by.id('search-message-view-input')).typeText('30\n');
|
||||||
await waitFor(element(by.label('30')).atIndex(0)).toExist().withTimeout(5000);
|
await waitFor(element(by.text('30')).atIndex(0)).toExist().withTimeout(5000);
|
||||||
await element(by.label('30')).atIndex(0).tap();
|
await element(by.text('30')).atIndex(0).tap();
|
||||||
await waitForLoading();
|
await waitForLoading();
|
||||||
await expect(element(by.label('30'))).toExist();
|
await expect(element(by.text('30'))).toExist();
|
||||||
await expect(element(by.label('31'))).toExist();
|
await expect(element(by.text('31'))).toExist();
|
||||||
await expect(element(by.label('32'))).toExist();
|
await expect(element(by.text('32'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load newer and older messages', async() => {
|
it('should load newer and older messages', async() => {
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('down', 'fast', 0.8);
|
await element(by.id('room-view-messages')).atIndex(0).swipe('down', 'fast', 0.8);
|
||||||
await waitFor(element(by.label('5'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('5'))).toExist().withTimeout(5000);
|
||||||
await waitFor(element(by.label('Load Older'))).toExist().withTimeout(5000);
|
await waitFor(element(by.label('Load Older'))).toExist().withTimeout(5000);
|
||||||
await element(by.label('Load Older')).atIndex(0).tap();
|
await element(by.label('Load Older')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label('4'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('4'))).toExist().withTimeout(5000);
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('down', 'fast', 0.5);
|
await element(by.id('room-view-messages')).atIndex(0).swipe('down', 'fast', 0.5);
|
||||||
await waitFor(element(by.label('1'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('1'))).toExist().withTimeout(5000);
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'fast', 0.5);
|
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'fast', 0.5);
|
||||||
await waitFor(element(by.label('25'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('25'))).toExist().withTimeout(5000);
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'fast', 0.5);
|
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'fast', 0.5);
|
||||||
await waitFor(element(by.label('50'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('50'))).toExist().withTimeout(5000);
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'slow', 0.5);
|
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'slow', 0.5);
|
||||||
await waitFor(element(by.label('Load Newer'))).toExist().withTimeout(5000);
|
await waitFor(element(by.label('Load Newer'))).toExist().withTimeout(5000);
|
||||||
await element(by.label('Load Newer')).atIndex(0).tap();
|
await element(by.label('Load Newer')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label('104'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('104'))).toExist().withTimeout(5000);
|
||||||
await waitFor(element(by.label('Load Newer'))).toExist().withTimeout(5000);
|
await waitFor(element(by.label('Load Newer'))).toExist().withTimeout(5000);
|
||||||
await element(by.label('Load Newer')).atIndex(0).tap();
|
await element(by.label('Load Newer')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label('154'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('154'))).toExist().withTimeout(5000);
|
||||||
await waitFor(element(by.label('Load Newer'))).toExist().withTimeout(5000);
|
await waitFor(element(by.label('Load Newer'))).toExist().withTimeout(5000);
|
||||||
await element(by.label('Load Newer')).atIndex(0).tap();
|
await element(by.label('Load Newer')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label('Load Newer'))).toNotExist().withTimeout(5000);
|
await waitFor(element(by.label('Load Newer'))).toNotExist().withTimeout(5000);
|
||||||
await expect(element(by.label('Load More'))).toNotExist();
|
await expect(element(by.label('Load More'))).toNotExist();
|
||||||
await expect(element(by.label('201'))).toExist();
|
await expect(element(by.text('201'))).toExist();
|
||||||
await expect(element(by.label('202'))).toExist();
|
await expect(element(by.text('202'))).toExist();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const expectThreadMessages = async(message) => {
|
const expectThreadMessages = async(message) => {
|
||||||
await waitFor(element(by.id('room-view-title-jumping-thread'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('room-view-title-jumping-thread'))).toExist().withTimeout(5000);
|
||||||
await expect(element(by.label(message))).toExist();
|
await expect(element(by.text(message))).toExist();
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Threads', () => {
|
describe('Threads', () => {
|
||||||
it('should navigate to a thread from another room', async() => {
|
it('should navigate to a thread from another room', async() => {
|
||||||
await navigateToRoom('jumping');
|
await navigateToRoom('jumping');
|
||||||
await waitFor(element(by.label('Go to jumping-thread\'s thread')).atIndex(0)).toExist().withTimeout(5000);
|
await waitFor(element(by.text('Go to jumping-thread\'s thread')).atIndex(0)).toExist().withTimeout(5000);
|
||||||
await element(by.label('Go to jumping-thread\'s thread')).atIndex(0).tap();
|
await element(by.text('Go to jumping-thread\'s thread')).atIndex(0).tap();
|
||||||
await waitForLoading();
|
await waitForLoading();
|
||||||
await expectThreadMessages('Go to jumping-thread\'s thread');
|
await expectThreadMessages('Go to jumping-thread\'s thread');
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should tap on thread message from main room', async() => {
|
it('should tap on thread message from main room', async() => {
|
||||||
await waitFor(element(by.label('thread message sent to main room')).atIndex(0)).toExist().withTimeout(5000);
|
await waitFor(element(by.text('thread message sent to main room')).atIndex(0)).toExist().withTimeout(5000);
|
||||||
await element(by.label('thread message sent to main room')).atIndex(0).tap();
|
await element(by.text('thread message sent to main room')).atIndex(0).tap();
|
||||||
await expectThreadMessages('thread message sent to main room');
|
await expectThreadMessages('thread message sent to main room');
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should tap on quote', async() => {
|
it('should tap on quote', async() => {
|
||||||
await waitFor(element(by.label('quoted'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('quoted'))).toExist().withTimeout(5000);
|
||||||
await element(by.label('quoted')).atIndex(0).tap();
|
await element(by.text('quoted')).atIndex(0).tap();
|
||||||
await expectThreadMessages('quoted');
|
await expectThreadMessages('quoted');
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
@ -147,8 +147,8 @@ describe('Threads', () => {
|
||||||
await element(by.id('room-view-search')).atIndex(0).tap();
|
await element(by.id('room-view-search')).atIndex(0).tap();
|
||||||
await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(5000);
|
||||||
await element(by.id('search-message-view-input')).typeText('to be searched\n');
|
await element(by.id('search-message-view-input')).typeText('to be searched\n');
|
||||||
await waitFor(element(by.label('to be searched'))).toExist().withTimeout(5000);
|
await waitFor(element(by.text('to be searched'))).toExist().withTimeout(5000);
|
||||||
await element(by.label('to be searched')).atIndex(1).tap();
|
await element(by.text('to be searched')).atIndex(1).tap();
|
||||||
await expectThreadMessages('to be searched');
|
await expectThreadMessages('to be searched');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue