chore: config tauri web driver test (#1947)

* chore: setup tauri test

* chore: update test

* chore: update test

* chore: update test

* chore: update test

* refactor: test folder location

* chore: remove deps

* ci: fix build

---------

Co-authored-by: appflowy <annie@appflowy.io>
Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
Lucas.Xu
2023-03-11 12:07:31 +07:00
committed by GitHub
parent 688d55e00f
commit 668e1196d1
10 changed files with 133 additions and 82 deletions

View File

@ -1,8 +0,0 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
globals: {
window: {},
},
};

View File

@ -12,8 +12,7 @@
"test:errors": "eslint --quiet --ext .js,.ts,.tsx .", "test:errors": "eslint --quiet --ext .js,.ts,.tsx .",
"test:prettier": "yarn prettier --list-different src", "test:prettier": "yarn prettier --list-different src",
"tauri:clean": "cargo make --cwd .. tauri_clean", "tauri:clean": "cargo make --cwd .. tauri_clean",
"tauri:dev": "tauri dev", "tauri:dev": "tauri dev"
"test": "jest"
}, },
"dependencies": { "dependencies": {
"@emotion/react": "^11.10.6", "@emotion/react": "^11.10.6",
@ -26,7 +25,7 @@
"i18next": "^22.4.10", "i18next": "^22.4.10",
"i18next-browser-languagedetector": "^7.0.1", "i18next-browser-languagedetector": "^7.0.1",
"is-hotkey": "^0.2.0", "is-hotkey": "^0.2.0",
"jest": "^29.4.3", "jest": "^29.5.0",
"nanoid": "^4.0.0", "nanoid": "^4.0.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
@ -46,8 +45,6 @@
"@tauri-apps/cli": "^1.2.2", "@tauri-apps/cli": "^1.2.2",
"@types/google-protobuf": "^3.15.6", "@types/google-protobuf": "^3.15.6",
"@types/is-hotkey": "^0.1.7", "@types/is-hotkey": "^0.1.7",
"@types/jest": "^29.4.0",
"@types/mocha": "^10.0.1",
"@types/node": "^18.7.10", "@types/node": "^18.7.10",
"@types/react": "^18.0.15", "@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
@ -62,7 +59,6 @@
"prettier": "2.8.4", "prettier": "2.8.4",
"prettier-plugin-tailwindcss": "^0.2.2", "prettier-plugin-tailwindcss": "^0.2.2",
"tailwindcss": "^3.2.7", "tailwindcss": "^3.2.7",
"ts-jest": "^29.0.5",
"typescript": "^4.6.4", "typescript": "^4.6.4",
"vite": "^4.0.0" "vite": "^4.0.0"
} }

View File

@ -9,7 +9,7 @@ export const GetStarted = () => {
<> <>
<form onSubmit={(e) => e.preventDefault()} method='POST'> <form onSubmit={(e) => e.preventDefault()} method='POST'>
<div className='relative flex h-screen w-screen flex-col items-center justify-center gap-12 text-center'> <div className='relative flex h-screen w-screen flex-col items-center justify-center gap-12 text-center'>
<div className='flex h-10 w-10 justify-center'> <div className='flex h-10 w-10 justify-center' id='appflowy'>
<AppflowyLogo /> <AppflowyLogo />
</div> </div>
@ -19,8 +19,8 @@ export const GetStarted = () => {
</span> </span>
</div> </div>
<div className='flex w-full max-w-[340px] flex-col gap-6 '> <div id='Get-Started' className='flex w-full max-w-[340px] flex-col gap-6 ' aria-label='Get-Started' >
<Button size={'primary'} onClick={() => onAutoSignInClick()}> <Button size={'primary'} onClick={() => onAutoSignInClick()} >
{t('signUp.getStartedText')} {t('signUp.getStartedText')}
</Button> </Button>
</div> </div>

View File

@ -13,7 +13,7 @@ export const PageOptions = () => {
Share Share
</Button> </Button>
<button className={'relative h-8 w-8'} onClick={onOptionsClick}> <button id='option-button' className={'relative h-8 w-8'} onClick={onOptionsClick} >
<Details2Svg></Details2Svg> <Details2Svg></Details2Svg>
</button> </button>
</div> </div>

View File

@ -1,42 +1,43 @@
import { AuthBackendService, UserBackendService } from '../appflowy_app/stores/effects/user/user_bd_svc'; export {}
import { randomFillSync } from 'crypto'; // import { AuthBackendService, UserBackendService } from '../appflowy_app/stores/effects/user/user_bd_svc';
import { nanoid } from '@reduxjs/toolkit'; // import { randomFillSync } from 'crypto';
// import { nanoid } from '@reduxjs/toolkit';
beforeAll(() => { // beforeAll(() => {
//@ts-ignore // //@ts-ignore
window.crypto = { // window.crypto = {
// @ts-ignore // // @ts-ignore
getRandomValues: function (buffer) { // getRandomValues: function (buffer) {
// @ts-ignore // // @ts-ignore
return randomFillSync(buffer); // return randomFillSync(buffer);
}, // },
}; // };
}); // });
describe('User backend service', () => { // describe('User backend service', () => {
it('sign up', async () => { // it('sign up', async () => {
const service = new AuthBackendService(); // const service = new AuthBackendService();
const result = await service.autoSignUp(); // const result = await service.autoSignUp();
expect(result.ok).toBeTruthy; // expect(result.ok).toBeTruthy;
}); // });
it('sign in', async () => { // it('sign in', async () => {
const authService = new AuthBackendService(); // const authService = new AuthBackendService();
const email = nanoid(4) + '@appflowy.io'; // const email = nanoid(4) + '@appflowy.io';
const password = nanoid(10); // const password = nanoid(10);
const signUpResult = await authService.signUp({ name: 'nathan', email: email, password: password }); // const signUpResult = await authService.signUp({ name: 'nathan', email: email, password: password });
expect(signUpResult.ok).toBeTruthy; // expect(signUpResult.ok).toBeTruthy;
const signInResult = await authService.signIn({ email: email, password: password }); // const signInResult = await authService.signIn({ email: email, password: password });
expect(signInResult.ok).toBeTruthy; // expect(signInResult.ok).toBeTruthy;
}); // });
it('get user profile', async () => { // it('get user profile', async () => {
const service = new AuthBackendService(); // const service = new AuthBackendService();
const result = await service.autoSignUp(); // const result = await service.autoSignUp();
const userProfile = result.unwrap(); // const userProfile = result.unwrap();
const userService = new UserBackendService(userProfile.id); // const userService = new UserBackendService(userProfile.id);
expect((await userService.getUserProfile()).unwrap()).toBe(userProfile); // expect((await userService.getUserProfile()).unwrap()).toBe(userProfile);
}); // });
}); // });

View File

@ -1,14 +0,0 @@
describe('My Login application', () => {
it('should login with valid credentials', async () => {
await browser.url(`https://the-internet.herokuapp.com/login`)
await $('#username').setValue('tomsmith')
await $('#password').setValue('SuperSecretPassword!')
await $('button[type="submit"]').click()
await expect($('#flash')).toBeExisting()
await expect($('#flash')).toHaveTextContaining(
'You logged into a secure area!')
})
})

View File

@ -1,13 +0,0 @@
{
"compilerOptions": {
"moduleResolution": "node",
"module": "ESNext",
"types": [
"node",
"@wdio/globals/types",
"expect-webdriverio",
"@wdio/mocha-framework"
],
"target": "es2022"
}
}

View File

@ -0,0 +1,13 @@
{
"name": "selenium",
"version": "1.0.0",
"private": true,
"scripts": {
"test": "mocha"
},
"dependencies": {
"chai": "^4.3.4",
"mocha": "^9.0.3",
"selenium-webdriver": "^4.0.0-beta.4"
}
}

View File

@ -0,0 +1,76 @@
const os = require("os");
const path = require("path");
const { expect } = require("chai");
const { spawn, spawnSync } = require("child_process");
const { Builder, By, Capabilities, until } = require("selenium-webdriver");
const { elementIsVisible, elementLocated } = require("selenium-webdriver/lib/until.js");
// create the path to the expected application binary
const application = path.resolve(
__dirname,
"..",
"..",
"..",
"src-tauri",
"target",
"release",
"appflowy_tauri"
);
// keep track of the webdriver instance we create
let driver;
// keep track of the tauri-driver process we start
let tauriDriver;
before(async function() {
// set timeout to 2 minutes to allow the program to build if it needs to
this.timeout(120000);
// ensure the program has been built
spawnSync("cargo", ["build", "--release"]);
// start tauri-driver
tauriDriver = spawn(
path.resolve(os.homedir(), ".cargo", "bin", "tauri-driver"),
[],
{ stdio: [null, process.stdout, process.stderr] }
);
const capabilities = new Capabilities();
capabilities.set("tauri:options", { application });
capabilities.setBrowserName("wry");
// start the webdriver client
driver = await new Builder()
.withCapabilities(capabilities)
.usingServer("http://localhost:4444/")
.build();
});
after(async function() {
// stop the webdriver session
await driver.quit();
// kill the tauri-driver process
tauriDriver.kill();
});
describe("AppFlowy Unit Test", () => {
it("should find get started button", async () => {
// should sign out if already sign in
const getStartedButton = await driver.wait(until.elementLocated(By.xpath("//*[@id=\"root\"]/form/div/div[3]")));
getStartedButton.click();
});
it("should get sign out button", async (done) => {
// const optionButton = await driver.wait(until.elementLocated(By.css('*[test-id=option-button]')));
// const optionButton = await driver.wait(until.elementLocated(By.id('option-button')));
// const optionButton = await driver.wait(until.elementLocated(By.css('[aria-label=option]')));
// Currently, only the find className is work
const optionButton = await driver.wait(until.elementLocated(By.className("relative h-8 w-8")));
optionButton.click();
await new Promise((resolve) => setTimeout(resolve, 4000));
});
});

View File

@ -13,7 +13,7 @@ script_runner = "@shell"
[tasks.install_tauri_protobuf.linux] [tasks.install_tauri_protobuf.linux]
script = """ script = """
npm install -g protoc-gen-ts sudo npm install -g protoc-gen-ts
""" """
script_runner = "@shell" script_runner = "@shell"