chore: initialize repository with gitignore

This commit is contained in:
2026-04-13 07:16:39 +08:00
commit d3c18e8912
81 changed files with 4429 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
apply plugin: 'com.android.application'
configurations.configureEach {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}
android {
namespace 'com.example.task1registerform'
compileSdk 34
defaultConfig {
applicationId 'com.example.task1registerform'
minSdk 26
targetSdk 34
versionCode 1
versionName '1.0'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
buildTypes {
release {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
testOptions {
animationsDisabled true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.core:core:1.13.1'
androidTestImplementation 'androidx.test:core:1.5.0'
androidTestImplementation 'androidx.test:runner:1.5.2'
androidTestImplementation 'androidx.test:rules:1.5.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.5.1'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1'
androidTestImplementation 'junit:junit:4.13.2'
}
@@ -0,0 +1,127 @@
package com.example.task1registerform;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import android.app.UiAutomation;
import android.view.accessibility.AccessibilityEvent;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.TimeoutException;
@RunWith(AndroidJUnit4.class)
public class MainActivityFormTest {
private ActivityScenario<MainActivity> activityScenario;
@Before
public void setUp() {
activityScenario = ActivityScenario.launch(MainActivity.class);
}
@After
public void tearDown() {
activityScenario.close();
}
/**
* 任意输入框为空时,应提示完善信息并保持输入框内容不变。
*/
@Test
public void testEmptyFields_ShowIncompleteToast_AndKeepEmptyInputs() {
onView(withId(R.id.et_name)).perform(replaceText(""), closeSoftKeyboard());
onView(withId(R.id.et_phone)).perform(replaceText(""), closeSoftKeyboard());
onView(withId(R.id.et_email)).perform(replaceText(""), closeSoftKeyboard());
clickAndAssertToast(R.id.btn_register, "请完善所有注册信息");
onView(withId(R.id.et_name)).check(matches(withText("")));
onView(withId(R.id.et_phone)).check(matches(withText("")));
onView(withId(R.id.et_email)).check(matches(withText("")));
}
/**
* 手机号不满足 11 位数字规则时,应提示手机号错误并保留当前输入。
*/
@Test
public void testInvalidPhone_ShowPhoneToast_AndKeepInputs() {
fillForm("张三", "123456", "zhangsan@example.com");
clickAndAssertToast(R.id.btn_register, "请输入正确的11位手机号");
onView(withId(R.id.et_name)).check(matches(withText("张三")));
onView(withId(R.id.et_phone)).check(matches(withText("123456")));
onView(withId(R.id.et_email)).check(matches(withText("zhangsan@example.com")));
}
/**
* 邮箱格式错误时,应提示邮箱错误并保留用户已经输入的数据。
*/
@Test
public void testInvalidEmail_ShowEmailToast_AndKeepInputs() {
fillForm("李四", "13812345678", "invalid-email");
clickAndAssertToast(R.id.btn_register, "请输入正确的邮箱地址");
onView(withId(R.id.et_name)).check(matches(withText("李四")));
onView(withId(R.id.et_phone)).check(matches(withText("13812345678")));
onView(withId(R.id.et_email)).check(matches(withText("invalid-email")));
}
/**
* 所有输入均合法时,应提示注册成功并清空全部输入框。
*/
@Test
public void testRegisterSuccess_ShowSuccessToast_AndClearInputs() {
fillForm("王五", "13912345678", "wangwu@example.com");
clickAndAssertToast(R.id.btn_register, "注册成功");
onView(withId(R.id.et_name)).check(matches(withText("")));
onView(withId(R.id.et_phone)).check(matches(withText("")));
onView(withId(R.id.et_email)).check(matches(withText("")));
}
private void fillForm(String name, String phone, String email) {
onView(withId(R.id.et_name)).perform(replaceText(name), closeSoftKeyboard());
onView(withId(R.id.et_phone)).perform(replaceText(phone), closeSoftKeyboard());
onView(withId(R.id.et_email)).perform(replaceText(email), closeSoftKeyboard());
}
private void clickAndAssertToast(int viewId, String message) {
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
try {
AccessibilityEvent event = uiAutomation.executeAndWaitForEvent(
() -> onView(withId(viewId)).perform(click()),
candidate -> candidate.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED
&& containsText(candidate, message),
5000
);
assertNotNull(event);
} catch (TimeoutException exception) {
fail("Toast not shown: " + message);
}
}
private boolean containsText(AccessibilityEvent event, String message) {
for (CharSequence text : event.getText()) {
if (message.contentEquals(text)) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="@string/app_name"
android:theme="@style/Theme.Task1RegisterForm">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,70 @@
package com.example.task1registerform;
import android.os.Bundle;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private EditText etName;
private EditText etPhone;
private EditText etEmail;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etName = findViewById(R.id.et_name);
etPhone = findViewById(R.id.et_phone);
etEmail = findViewById(R.id.et_email);
Button btnRegister = findViewById(R.id.btn_register);
btnRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleRegister();
}
});
}
private void handleRegister() {
String name = etName.getText().toString().trim();
String phone = etPhone.getText().toString().trim();
String email = etEmail.getText().toString().trim();
// 按实验要求顺序完成表单校验,确保 Toast 与场景一一对应。
if (name.isEmpty() || phone.isEmpty() || email.isEmpty()) {
showToast(R.string.toast_complete_info);
return;
}
if (!phone.matches("^\\d{11}$")) {
showToast(R.string.toast_invalid_phone);
return;
}
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
showToast(R.string.toast_invalid_email);
return;
}
showToast(R.string.toast_register_success);
clearInputs();
}
private void clearInputs() {
etName.setText("");
etPhone.setText("");
etEmail.setText("");
}
private void showToast(int messageResId) {
Toast.makeText(this, getString(messageResId), Toast.LENGTH_SHORT).show();
}
}
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="@string/title_register_form"
android:textSize="22sp"
android:textStyle="bold" />
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="@string/hint_name"
android:inputType="textPersonName" />
<EditText
android:id="@+id/et_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="@string/hint_phone"
android:inputType="phone" />
<EditText
android:id="@+id/et_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:hint="@string/hint_email"
android:inputType="textEmailAddress" />
<Button
android:id="@+id/btn_register"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/action_register" />
</LinearLayout>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Task 1 Register Form</string>
<string name="title_register_form">用户注册表单</string>
<string name="hint_name">请输入姓名</string>
<string name="hint_phone">请输入 11 位手机号</string>
<string name="hint_email">请输入邮箱地址</string>
<string name="action_register">提交注册</string>
<string name="toast_complete_info">请完善所有注册信息</string>
<string name="toast_invalid_phone">请输入正确的11位手机号</string>
<string name="toast_invalid_email">请输入正确的邮箱地址</string>
<string name="toast_register_success">注册成功</string>
</resources>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Task1RegisterForm" parent="Theme.AppCompat.Light.NoActionBar" />
</resources>