mirror of
https://github.com/Akomry/sae302_applicom.git
synced 2025-12-06 08:43:54 +00:00
Merge branch 'dev-contacts' into 'dev'
feat(contacts): ajout et gestion de la classe contact See merge request iut_rt/but2/sae302-applicom/bouclyma!2
This commit is contained in:
commit
5805e55209
14 changed files with 684 additions and 28 deletions
16
chat/pom.xml
16
chat/pom.xml
|
|
@ -25,6 +25,22 @@
|
|||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>18</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-swing</artifactId>
|
||||
<version>19</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>5.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.synedra</groupId>
|
||||
<artifactId>validatorfx</artifactId>
|
||||
<version>0.5.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,13 @@ module rtgre.chat {
|
|||
requires javafx.controls;
|
||||
requires javafx.fxml;
|
||||
requires java.logging;
|
||||
requires java.desktop;
|
||||
requires javafx.swing;
|
||||
requires net.synedra.validatorfx;
|
||||
|
||||
|
||||
opens rtgre.chat to javafx.fxml;
|
||||
exports rtgre.chat;
|
||||
exports rtgre.chat.graphisme;
|
||||
opens rtgre.chat.graphisme to javafx.fxml;
|
||||
}
|
||||
|
|
@ -15,8 +15,8 @@ import java.util.logging.Logger;
|
|||
|
||||
public class ChatApplication extends Application {
|
||||
public static final Logger LOGGER = Logger.getLogger(ChatApplication.class.getCanonicalName());
|
||||
|
||||
public class EssaiLogger {
|
||||
/* . . . */
|
||||
static {
|
||||
try {
|
||||
InputStream is = EssaiLogger.class.getClassLoader()
|
||||
|
|
@ -26,8 +26,8 @@ public class ChatApplication extends Application {
|
|||
LOGGER.log(Level.INFO, "Cannot read configuration file", e);
|
||||
}
|
||||
}
|
||||
/* . . . */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage stage) throws IOException {
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(ChatApplication.class.getResource("chat-view.fxml"));
|
||||
|
|
|
|||
|
|
@ -2,22 +2,47 @@ package rtgre.chat;
|
|||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.embed.swing.SwingFXUtils;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.Event;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import net.synedra.validatorfx.Check;
|
||||
import net.synedra.validatorfx.TooltipWrapper;
|
||||
import net.synedra.validatorfx.Validator;
|
||||
import rtgre.chat.graphisme.ContactListViewCell;
|
||||
import rtgre.modeles.Contact;
|
||||
import rtgre.modeles.ContactMap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static rtgre.chat.ChatApplication.LOGGER;
|
||||
|
||||
public class ChatController implements Initializable {
|
||||
|
||||
private static final Pattern LOGIN_PATTERN = Pattern.compile("^([a-z][a-z0-9]{2,7})$");
|
||||
private static final Pattern HOST_PATTERN = Pattern.compile("/^[a-z]*((\\:?)\\d{1,5})?$/gm");
|
||||
public MenuItem hostAddMenuItem;
|
||||
public MenuItem avatarMenuItem;
|
||||
public MenuItem aboutMenuItem;
|
||||
|
|
@ -28,11 +53,15 @@ public class ChatController implements Initializable {
|
|||
public SplitPane exchangeSplitPane;
|
||||
public ListView postListView;
|
||||
public ListView roomsListView;
|
||||
public ListView contactListView;
|
||||
public ListView contactsListView;
|
||||
public TextField messageTextField;
|
||||
public Button sendButton;
|
||||
public Label statusLabel;
|
||||
public Label dateTimeLabel;
|
||||
public Contact contact;
|
||||
private ContactMap contactMap = new ContactMap();
|
||||
private ObservableList<Contact> contactObservableList = FXCollections.observableArrayList();
|
||||
Validator validatorLogin = new Validator();
|
||||
|
||||
|
||||
@Override
|
||||
|
|
@ -53,13 +82,74 @@ public class ChatController implements Initializable {
|
|||
|
||||
statusLabel.setText("not connected to " + hostComboBox.getValue());
|
||||
|
||||
connectionButton.disableProperty().bind(validatorLogin.containsErrorsProperty());
|
||||
connectionButton.selectedProperty().addListener(this::handleConnection);
|
||||
loginTextField.disableProperty().bind(connectionButton.selectedProperty());
|
||||
hostComboBox.disableProperty().bind(connectionButton.selectedProperty());
|
||||
|
||||
avatarMenuItem.setOnAction(this::handleAvatarChange);
|
||||
avatarImageView.setOnMouseClicked(this::handleAvatarChange);
|
||||
|
||||
initContactListView();
|
||||
|
||||
validatorLogin.createCheck()
|
||||
.dependsOn("login", loginTextField.textProperty())
|
||||
.withMethod(this::checkLogin)
|
||||
.decorates(loginTextField)
|
||||
.immediate();
|
||||
|
||||
|
||||
/* /!\ Set-up d'environnement de test /!\ */
|
||||
/* -------------------------------------- */
|
||||
loginTextField.setText("riri");
|
||||
connectionButton.setSelected(true);
|
||||
}
|
||||
|
||||
private void handleAvatarChange(Event event) {
|
||||
/**
|
||||
* Ouvre une fenêtre de dialogue permettant de choisir son avatar
|
||||
*/
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
Stage stage = (Stage) avatarImageView.getScene().getWindow();
|
||||
fileChooser.setTitle("Select Avatar");
|
||||
fileChooser.getExtensionFilters().addAll(
|
||||
new FileChooser.ExtensionFilter("Image Files", "*.png", "*.jpg")
|
||||
);
|
||||
File selectedFile = fileChooser.showOpenDialog(stage);
|
||||
if (selectedFile != null) {
|
||||
avatarImageView.setImage(new Image(selectedFile.toURI().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void handleConnection(Observable observable) {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
if (connectionButton.isSelected()) {
|
||||
java.awt.Image img = SwingFXUtils.fromFXImage(this.avatarImageView.getImage(), null);
|
||||
this.contact = new Contact(loginTextField.getText(), img);
|
||||
contactMap.put(this.contact.getLogin(), this.contact);
|
||||
System.out.println("Nouveau contact : " + contact);
|
||||
System.out.println(contactMap);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkLogin(Check.Context context) {
|
||||
String login = context.get("login");
|
||||
if (!LOGIN_PATTERN.matcher(login).matches()) {
|
||||
context.error("Format de login non respecté");
|
||||
}
|
||||
if (login.equals("system")) {
|
||||
context.error("Le login ne peut pas être system");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void statusNameUpdate(Event event) {
|
||||
statusLabel.setText("not connected to " + hostComboBox.getValue());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -67,7 +157,6 @@ public class ChatController implements Initializable {
|
|||
while (true) {
|
||||
try {
|
||||
String datetime = "%1$ta %1$te %1$tb %1$tY - %1$tH:%1$tM".formatted(new Date());
|
||||
// System.out.println(datetime);
|
||||
Platform.runLater(() -> dateTimeLabel.setText(datetime));
|
||||
Thread.sleep(60000);
|
||||
} catch (Exception e) {
|
||||
|
|
@ -76,4 +165,20 @@ public class ChatController implements Initializable {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private void initContactListView() {
|
||||
try {
|
||||
contactsListView.setCellFactory(contactListView -> new ContactListViewCell());
|
||||
contactsListView.setItems(contactObservableList);
|
||||
File avatars = new File(getClass().getResource("avatars.png").toURI());
|
||||
Contact riri = new Contact("riri", false, avatars);
|
||||
Contact fifi = new Contact("fifi", true, avatars);
|
||||
contactObservableList.add(riri);
|
||||
contactMap.add(riri);
|
||||
contactObservableList.add(fifi);
|
||||
contactMap.add(fifi);
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package rtgre.chat.graphisme;
|
||||
|
||||
import rtgre.chat.ChatController;
|
||||
import javafx.embed.swing.SwingFXUtils;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import rtgre.modeles.Contact;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import static rtgre.chat.ChatApplication.LOGGER;
|
||||
|
||||
/**
|
||||
* Classe modélisant la fabrique de cellule de la vue des contacts
|
||||
* visibles/connectés {@link ChatController#contactsListView}.
|
||||
*
|
||||
* @see ListCell
|
||||
*/
|
||||
public class ContactListViewCell extends ListCell<Contact> {
|
||||
|
||||
/**
|
||||
* Callback déclenchée à chaque modification d'un objet d'une liste d'observable.
|
||||
*
|
||||
* @param contact Le contact à mettre à jour
|
||||
* @param empty La liste de cellule doit-elle être complètement remise à zéro ?
|
||||
*/
|
||||
@Override
|
||||
protected void updateItem(Contact contact, boolean empty) {
|
||||
super.updateItem(contact, empty);
|
||||
if (empty) {
|
||||
setGraphic(null);
|
||||
}
|
||||
else {
|
||||
// Cas d'un contact
|
||||
updateContact(contact);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mise à jour de la cellule d'un contact.
|
||||
*
|
||||
* @param contact Le contact à mettre à jour
|
||||
*/
|
||||
|
||||
private void updateContact(Contact contact) {
|
||||
LOGGER.finest("Mise à jour de " + contact);
|
||||
|
||||
String unreadCountNotif = (contact.getUnreadCount() == 0) ? "" : " (%d)".formatted(contact.getUnreadCount());
|
||||
LOGGER.finest("unread: %s %s".formatted(contact.getLogin(), unreadCountNotif));
|
||||
Text loginText = new Text(contact.getLogin() + unreadCountNotif);
|
||||
loginText.setFont(Font.font(null, 12)); // FontWeight.BOLD, 14));
|
||||
loginText.setFill(contact.isConnected() ? Color.BLACK : Color.GRAY);
|
||||
|
||||
Circle circle = new Circle(5, 5, 5);
|
||||
circle.setFill(contact.isConnected() ? Color.CADETBLUE : Color.FIREBRICK);
|
||||
// circle.setOpacity(contact.is_connected() ? 1 : 0.5);
|
||||
|
||||
Image avatar;
|
||||
ImageView view = new ImageView();
|
||||
|
||||
if (contact.getAvatar() != null) {
|
||||
avatar = SwingFXUtils.toFXImage((BufferedImage) contact.getAvatar(), null);
|
||||
view = new ImageView(avatar);
|
||||
}
|
||||
view.setOpacity(contact.isConnected() ? 1 : 0.5);
|
||||
view.setFitWidth(15);
|
||||
view.setFitHeight(15);
|
||||
|
||||
HBox temp = new HBox(circle);
|
||||
temp.setAlignment(Pos.CENTER_RIGHT);
|
||||
HBox.setHgrow(temp, Priority.ALWAYS);
|
||||
HBox hBox = new HBox(view, loginText, temp);
|
||||
hBox.setSpacing(5.0);
|
||||
hBox.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
setGraphic(hBox);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
122
chat/src/main/java/rtgre/modeles/Contact.java
Normal file
122
chat/src/main/java/rtgre/modeles/Contact.java
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
package rtgre.modeles;
|
||||
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Contact {
|
||||
protected String login;
|
||||
protected java.awt.Image avatar;
|
||||
protected boolean connected;
|
||||
protected String currentRoom;
|
||||
|
||||
public Contact(String login, java.awt.Image avatar) {
|
||||
/**
|
||||
* Crée un objet Contact
|
||||
* @param: String login
|
||||
* @param: java.awt.Image avatar
|
||||
*/
|
||||
this.login = login;
|
||||
this.avatar = avatar;
|
||||
this.connected = false;
|
||||
this.currentRoom = null;
|
||||
}
|
||||
public Contact(String login, boolean connected, java.awt.Image avatar) {
|
||||
/**
|
||||
* Crée un objet Contact
|
||||
* @param: String login
|
||||
* @param: boolean connected
|
||||
* @param: java.awt.Image avatar
|
||||
*/
|
||||
this.login = login;
|
||||
this.avatar = avatar;
|
||||
this.connected = connected;
|
||||
this.currentRoom = null;
|
||||
}
|
||||
|
||||
public String getCurrentRoom() {
|
||||
return currentRoom;
|
||||
}
|
||||
|
||||
public Contact(String login, boolean connected, File banques_avatars) {
|
||||
/**
|
||||
* Crée un objet Contact
|
||||
* @param: String login
|
||||
* @param: boolean connected
|
||||
* @param: File banques_avatars
|
||||
*/
|
||||
this.login = login;
|
||||
try {
|
||||
this.avatar = avatarFromLogin(banques_avatars, login);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Impossible de créer l'utilisateur " + login);
|
||||
System.out.println(e.getMessage());
|
||||
System.out.println(banques_avatars);
|
||||
}
|
||||
this.connected = connected;
|
||||
this.currentRoom = null;
|
||||
}
|
||||
|
||||
|
||||
public String getLogin() {
|
||||
return this.login;
|
||||
}
|
||||
|
||||
public java.awt.Image getAvatar() {
|
||||
return this.avatar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "@" + this.login;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return this.connected;
|
||||
}
|
||||
|
||||
public void setConnected(boolean connected) {
|
||||
this.connected = connected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Contact contact = (Contact) o;
|
||||
return Objects.equals(login, contact.login);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(login);
|
||||
}
|
||||
|
||||
public int getUnreadCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static BufferedImage avatarFromLogin(File fichier, String login) throws IOException {
|
||||
/**
|
||||
* Renvoie une sous-image en fonction d'une banque d'image et d'un login.
|
||||
* @param: File fichier
|
||||
* @param: String login
|
||||
*/
|
||||
BufferedImage img = ImageIO.read(fichier);
|
||||
int width = img.getWidth() / 9;
|
||||
int height = img.getHeight();
|
||||
int n = Integer.remainderUnsigned(login.hashCode(), 9);
|
||||
return img.getSubimage(n*width, 0, width, height);
|
||||
}
|
||||
|
||||
public void setAvatarFromFile(File f) {
|
||||
try {
|
||||
this.avatar = avatarFromLogin(f, this.login);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Erreur : " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
12
chat/src/main/java/rtgre/modeles/ContactMap.java
Normal file
12
chat/src/main/java/rtgre/modeles/ContactMap.java
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package rtgre.modeles;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class ContactMap extends TreeMap<String, Contact> {
|
||||
public void add(Contact contact) {
|
||||
this.put(contact.login, contact);
|
||||
}
|
||||
|
||||
public Contact getContact(String login) {
|
||||
return this.get(login);
|
||||
}
|
||||
}
|
||||
BIN
chat/src/main/resources/rtgre/chat/avatar1.png
Normal file
BIN
chat/src/main/resources/rtgre/chat/avatar1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
chat/src/main/resources/rtgre/chat/avatar2.png
Normal file
BIN
chat/src/main/resources/rtgre/chat/avatar2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
BIN
chat/src/main/resources/rtgre/chat/avatars.png
Normal file
BIN
chat/src/main/resources/rtgre/chat/avatars.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -1,27 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.ListView?>
|
||||
<?import javafx.scene.control.Menu?>
|
||||
<?import javafx.scene.control.MenuBar?>
|
||||
<?import javafx.scene.control.MenuItem?>
|
||||
<?import javafx.scene.control.Separator?>
|
||||
<?import javafx.scene.control.SplitPane?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.control.ToggleButton?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.image.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
|
||||
<VBox alignment="CENTER" minHeight="400.0" minWidth="600.0" prefHeight="500.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="rtgre.chat.ChatController">
|
||||
<VBox alignment="CENTER" minHeight="400.0" minWidth="600.0" prefHeight="500.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="rtgre.chat.ChatController">
|
||||
<children>
|
||||
<MenuBar>
|
||||
<MenuBar VBox.vgrow="NEVER">
|
||||
<menus>
|
||||
<Menu mnemonicParsing="false" text="Edit">
|
||||
<items>
|
||||
|
|
@ -77,7 +63,7 @@
|
|||
<SplitPane dividerPositions="0.1" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0">
|
||||
<items>
|
||||
<ListView fx:id="roomsListView" prefHeight="200.0" prefWidth="200.0" />
|
||||
<ListView fx:id="contactListView" prefHeight="200.0" prefWidth="200.0" />
|
||||
<ListView fx:id="contactsListView" prefHeight="200.0" prefWidth="200.0" />
|
||||
</items>
|
||||
</SplitPane>
|
||||
</items>
|
||||
|
|
@ -111,7 +97,7 @@
|
|||
</children>
|
||||
</HBox>
|
||||
<Separator prefWidth="200.0" />
|
||||
<HBox>
|
||||
<HBox VBox.vgrow="NEVER">
|
||||
<children>
|
||||
<Label text="Status : " />
|
||||
<Label fx:id="statusLabel" text="Not connected" />
|
||||
|
|
|
|||
155
chat/src/test/java/rtgre/modeles/ContactBaseTest1.java
Normal file
155
chat/src/test/java/rtgre/modeles/ContactBaseTest1.java
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
package rtgre.modeles;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
/** Tests unitaires du modèle de base de Contact (étape 1) */
|
||||
|
||||
class ContactBaseTest1 {
|
||||
|
||||
static Class<?> classe = Contact.class;
|
||||
static String module = "rtgre.modeles";
|
||||
|
||||
@DisplayName("01-Structure de la classe Contact")
|
||||
@Nested
|
||||
class StructureTest {
|
||||
|
||||
static List<String> constructeursSignatures;
|
||||
static List<String> methodesSignatures;
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
Constructor<?>[] constructeurs = classe.getConstructors();
|
||||
constructeursSignatures = Arrays.stream(constructeurs).map(Constructor::toString).collect(Collectors.toList());
|
||||
Method[] methodes = classe.getDeclaredMethods();
|
||||
methodesSignatures = Arrays.stream(methodes).map(Method::toString).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributs
|
||||
*/
|
||||
static Stream<Arguments> attributsProvider() {
|
||||
return Stream.of(
|
||||
arguments("login", "java.lang.String", Modifier.PROTECTED),
|
||||
arguments("avatar", "java.awt.Image", Modifier.PROTECTED),
|
||||
arguments("connected", "boolean", Modifier.PROTECTED),
|
||||
arguments("currentRoom", "java.lang.String", Modifier.PROTECTED)
|
||||
);
|
||||
}
|
||||
|
||||
@DisplayName("Déclaration des attributs : nom, type et visibilité")
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributsProvider")
|
||||
void testDeclarationAttributs(String nom, String type, int modifier) throws NoSuchFieldException {
|
||||
Field field = classe.getDeclaredField(nom);
|
||||
Assertions.assertEquals(type, field.getType().getName(),
|
||||
"Type " + nom + " erroné : doit être " + type);
|
||||
Assertions.assertEquals(modifier, field.getModifiers(),
|
||||
"Visibilité " + nom + " erronée : doit être " + modifier);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeurs
|
||||
*/
|
||||
static Stream<Arguments> constructeursProvider() {
|
||||
return Stream.of(
|
||||
arguments("public %s.Contact(java.lang.String,java.awt.Image)")
|
||||
);
|
||||
}
|
||||
|
||||
@DisplayName("Déclaration des constructeurs (base)")
|
||||
@ParameterizedTest
|
||||
@MethodSource("constructeursProvider")
|
||||
void testConstructeurs1(String signature) {
|
||||
Assertions.assertTrue(constructeursSignatures.contains(String.format(signature, module)),
|
||||
String.format("Constructeur non déclaré : doit être %s\nalors que sont déclarés %s",
|
||||
signature, constructeursSignatures));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Méthodes
|
||||
*/
|
||||
static Stream<Arguments> methodesProvider1() {
|
||||
return Stream.of(
|
||||
arguments("getLogin", "public java.lang.String %s.Contact.getLogin()"),
|
||||
arguments("getAvatar", "public java.awt.Image %s.Contact.getAvatar()"),
|
||||
arguments("isConnected", "public boolean %s.Contact.isConnected()"),
|
||||
arguments("toString", "public boolean %s.Contact.isConnected()"),
|
||||
arguments("setConnected", "public java.lang.String %s.Contact.toString()"),
|
||||
arguments("equals", "public boolean %s.Contact.equals(java.lang.Object)")
|
||||
);
|
||||
}
|
||||
|
||||
@DisplayName("Déclaration des méthodes (base)")
|
||||
@ParameterizedTest
|
||||
@MethodSource("methodesProvider1")
|
||||
void testDeclarationMethodes1(String nom, String signature) {
|
||||
Assertions.assertTrue(methodesSignatures.contains(String.format(signature, module, module)),
|
||||
String.format("Méthode non déclarée : doit être %s\nalors que sont déclarés %s",
|
||||
signature, methodesSignatures));
|
||||
}
|
||||
|
||||
|
||||
@DisplayName("02-Instanciation et getters")
|
||||
@Nested
|
||||
class InstanciationContactTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("sans avatar : getters de login, connected")
|
||||
void TestConstructeurParDefautSansAvatar() {
|
||||
Contact riri = new Contact("riri", null);
|
||||
Assertions.assertEquals("riri", riri.getLogin(), "Login erroné");
|
||||
Assertions.assertFalse(riri.isConnected(), "Etat par défaut erroné");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@DisplayName("03-Modification")
|
||||
@Nested
|
||||
class ModificationContactTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Setter de connexion")
|
||||
void TestEtatConnexion() {
|
||||
Contact riri = new Contact("riri", null);
|
||||
riri.setConnected(true);
|
||||
Assertions.assertTrue(riri.isConnected(), "Changement d'état erroné");
|
||||
riri.setConnected(false);
|
||||
Assertions.assertFalse(riri.isConnected(), "Changement d'état erroné");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("04-Représentation textuelle")
|
||||
void TestToString() {
|
||||
Contact riri = new Contact("riri", null);
|
||||
Assertions.assertEquals("@riri", riri.toString(),
|
||||
"Représentation textuelle erronée");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("05-Egalité")
|
||||
void TestEquals() {
|
||||
Contact riri = new Contact("riri", null);
|
||||
Contact riri2 = new Contact("riri", null);
|
||||
Contact fifi = new Contact("fifi", null);
|
||||
Assertions.assertEquals(riri, riri2, "Comparaison erronée");
|
||||
Assertions.assertNotEquals(riri, fifi, "Comparaison erronée");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
47
chat/src/test/java/rtgre/modeles/ContactMapTest.java
Normal file
47
chat/src/test/java/rtgre/modeles/ContactMapTest.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package rtgre.modeles;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.TreeMap;
|
||||
|
||||
class ContactMapTest {
|
||||
|
||||
static Class<?> classe = ContactMap.class;
|
||||
|
||||
@DisplayName("01-Structure")
|
||||
@Nested
|
||||
class StructureContactMapTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Heritage")
|
||||
void testHeritage() {
|
||||
ContactMap contactMap = new ContactMap();
|
||||
Assertions.assertInstanceOf(TreeMap.class, contactMap, "doit hériter de TreeMap");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@DisplayName("02-Ajout")
|
||||
@Nested
|
||||
class AddTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Ajout d'un contact")
|
||||
void TestAdd() {
|
||||
Contact riri = new Contact("riri", null);
|
||||
ContactMap contactMap = new ContactMap();
|
||||
contactMap.add(riri);
|
||||
|
||||
Assertions.assertTrue(contactMap.containsKey("riri"),
|
||||
"Les clés sont les logins");
|
||||
Assertions.assertTrue(contactMap.containsValue(riri),
|
||||
"Les valeurs sont les contacts");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
120
chat/src/test/java/rtgre/modeles/ContactWithAvatarTest2.java
Normal file
120
chat/src/test/java/rtgre/modeles/ContactWithAvatarTest2.java
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
package rtgre.modeles;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
/** Tests unitaires du modèle de base de Contact (étape 1) */
|
||||
|
||||
class ContactWithAvatarTest2 {
|
||||
|
||||
static Class<?> classe = Contact.class;
|
||||
static String module = "rtgre.modeles";
|
||||
|
||||
@DisplayName("01-Structure de la classe Contact")
|
||||
@Nested
|
||||
class StructureTest {
|
||||
|
||||
static List<String> constructeursSignatures;
|
||||
static List<String> methodesSignatures;
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
Constructor<?>[] constructeurs = classe.getConstructors();
|
||||
constructeursSignatures = Arrays.stream(constructeurs).map(Constructor::toString).collect(Collectors.toList());
|
||||
Method[] methodes = classe.getDeclaredMethods();
|
||||
methodesSignatures = Arrays.stream(methodes).map(Method::toString).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Stream<Arguments> constructeursProvider2() {
|
||||
return Stream.of(
|
||||
arguments("public %s.Contact(java.lang.String,boolean,java.io.File)")
|
||||
);
|
||||
}
|
||||
// @Disabled("Jusqu'à ce que soit codé les avatars à partir d'un fichier")
|
||||
@DisplayName("Déclaration des constructeurs (avec avatars à partir d'un fichier)")
|
||||
@ParameterizedTest
|
||||
@MethodSource("constructeursProvider2")
|
||||
void testConstructeurs2(String signature) {
|
||||
Assertions.assertTrue(constructeursSignatures.contains(String.format(signature, module)),
|
||||
String.format("Constructeur non déclaré : doit être %s\nalors que sont déclarés %s",
|
||||
signature, constructeursSignatures));
|
||||
|
||||
}
|
||||
|
||||
|
||||
static Stream<Arguments> methodesProvider2() {
|
||||
return Stream.of(
|
||||
arguments("avatarFromLogin", "public static java.awt.image.BufferedImage %s.Contact.avatarFromLogin(java.io.File,java.lang.String) throws java.io.IOException"),
|
||||
arguments("setAvatarFromFile", "public void %s.Contact.setAvatarFromFile(java.io.File)")
|
||||
);
|
||||
}
|
||||
// @Disabled("Jusqu'à ce que soit codé les avatars à partir d'un fichier")
|
||||
@DisplayName("Déclaration des méthodes (avec avatars à partir d'un fichier)")
|
||||
@ParameterizedTest
|
||||
@MethodSource("methodesProvider2")
|
||||
void testDeclarationMethodes2(String nom, String signature) {
|
||||
Assertions.assertTrue(methodesSignatures.contains(String.format(signature, module, module)),
|
||||
String.format("Méthode non déclarée : doit être %s\nalors que sont déclarés %s",
|
||||
signature, methodesSignatures));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@DisplayName("02-Instanciation et getters")
|
||||
@Nested
|
||||
class InstanciationContactTest {
|
||||
|
||||
// @Disabled("Jusqu'à ce que soit codé les avatars à partir d'un fichier")
|
||||
@Test
|
||||
@DisplayName("avec avatar : getters de avatar")
|
||||
void TestConstructeurParDefautAvecAvatar() throws IOException {
|
||||
String work_dir = System.getProperty("user.dir");
|
||||
Assertions.assertTrue(work_dir.endsWith("chat"),
|
||||
"Le working dir doit être <projet>/chat/ et non : " + work_dir);
|
||||
File f = new File("src/main/resources/rtgre/chat/anonymous.png");
|
||||
Assertions.assertTrue(f.canRead(), "Fichier manquant " + f.getAbsolutePath());
|
||||
Image avatar = ImageIO.read(f);
|
||||
Contact fifi = new Contact("fifi", avatar);
|
||||
Assertions.assertEquals(avatar, fifi.getAvatar(), "Avatar erroné");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// @Disabled("Jusqu'à ce que soit codé les avatars à partir d'un fichier")
|
||||
@Nested
|
||||
@DisplayName("06-Avatar à partir d'un fichier")
|
||||
class AvatarFromFilesTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("A partir d'un fichier")
|
||||
void TestSetFromFile() throws IOException {
|
||||
String work_dir = System.getProperty("user.dir");
|
||||
Assertions.assertTrue(work_dir.endsWith("chat"),
|
||||
"Le working dir doit être <projet>/chat/ et non : " + work_dir);
|
||||
File f = new File("src/main/resources/rtgre/chat/avatar1.png");
|
||||
Assertions.assertTrue(f.canRead(), "Fichier manquant " + f.getAbsolutePath());
|
||||
Contact fifi = new Contact("fifi", null);
|
||||
fifi.setAvatarFromFile(f);
|
||||
Assertions.assertNotNull(fifi.getAvatar(), "Avatar non chargé");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue