Les objets JavaScript stockent les données de test, les réponses API, les fixtures Playwright et les configurations sous forme de paires clé-valeur. La déstructuration permet d'en extraire des valeurs précises proprement, sans répéter les accès aux propriétés.

Qu'est-ce qu'un objet ?

Un objet est une collection de paires clé-valeur. Les clés sont des strings ; les valeurs peuvent être de n'importe quel type :

const user = {
  id: 1,
  email: 'alice@example.com',
  role: 'admin',
  isActive: true,
};

Accédez aux valeurs avec la notation par point ou par crochet :

console.log(user.email);       // 'alice@example.com'
console.log(user['role']);     // 'admin'
console.log(user.id);         // 1

Modifiez les valeurs de la même façon :

user.email = 'newalice@example.com';
user.role = 'member';

Les objets dans les données de test

La plupart des données de test dans les tests Playwright s'expriment sous forme d'objets ou de tableaux d'objets :

const loginCredentials = {
  email: 'qa_test@example.com',
  password: 'ValidPass123!',
};

await page.fill('[data-testid="email"]', loginCredentials.email);
await page.fill('[data-testid="password"]', loginCredentials.password);

Collections de cas de test :

const INVALID_EMAILS = [
  { input: '',              description: 'empty' },
  { input: 'not-an-email', description: 'missing @' },
  { input: 'missing@',     description: 'missing domain' },
  { input: 'a@b',          description: 'no TLD' },
];

Chaque INVALID_EMAILS[0] est un objet avec les propriétés input et description.

La déstructuration : ce que c'est

La déstructuration permet d'extraire des valeurs d'un objet (ou d'un tableau) dans des variables individuelles en une seule ligne, au lieu de plusieurs.

Sans déstructuration :

const user = { id: 1, name: 'Alice', email: 'alice@test.com', role: 'admin' };

const id    = user.id;
const name  = user.name;
const email = user.email;
const role  = user.role;

Avec déstructuration :

const { id, name, email, role } = user;

Même résultat : quatre variables avec les mêmes valeurs, mais une ligne au lieu de quatre.

Renommer lors de la déstructuration

Pour que la variable porte un nom différent de la clé :

const config = {
  database_host: 'localhost',
  database_port: 5432,
};

const { database_host: host, database_port: port } = config;

console.log(host); // 'localhost'
console.log(port); // 5432

Valeurs par défaut dans la déstructuration

Si une clé risque de ne pas exister, on peut fournir une valeur par défaut :

const product = { name: 'Laptop', price: 999 };

const { name, price, discount = 0 } = product;
// discount = 0 (n'était pas dans product, utilise la valeur par défaut)

Déstructuration dans les paramètres de fonctions

C'est là que vous verrez le plus souvent la déstructuration dans Playwright : dans les fonctions de test.

// Sans déstructuration
test('user can log in', async (args) => {
  const page = args.page;
  const request = args.request;
  // ...
});

// Avec déstructuration (pattern standard Playwright)
test('user can log in', async ({ page, request }) => {
  // page et request disponibles directement
});

C'est de la déstructuration d'objet dans le paramètre de la fonction. La syntaxe { page, request } extrait ces propriétés depuis l'objet fixture que Playwright fournit.

C'est pour ça que le code de test Playwright semble avoir des "variables magiques" : elles sont déstructurées automatiquement depuis l'objet fixture.

Fixtures personnalisées : la déstructuration en pratique

Quand vous créez des fixtures personnalisées, vous écrirez ce pattern :

export const test = base.extend<{ loginPage: LoginPage }>({
  loginPage: async ({ page }, use) => {
    const loginPage = new LoginPage(page);
    await use(loginPage);
  },
});

// Puis dans un test :
test('login works', async ({ page, loginPage }) => {
  //                         ^^^ déstructuré depuis l'objet fixture
  await loginPage.login('user@test.com', 'pass');
});

Comprendre la déstructuration rend les fixtures compréhensibles.

Déstructuration imbriquée

Les objets peuvent contenir d'autres objets. On peut déstructurer plusieurs niveaux à la fois :

const apiResponse = {
  status: 200,
  data: {
    user: {
      id: 123,
      email: 'alice@test.com',
    },
    token: 'eyJhbGciOiJIUzI1NiJ9...',
  },
};

// Déstructuration imbriquée
const { status, data: { user: { id, email }, token } } = apiResponse;

console.log(status); // 200
console.log(id);     // 123
console.log(email);  // 'alice@test.com'
console.log(token);  // 'eyJhbGciOiJIUzI1NiJ9...'

Ça peut sembler complexe au premier abord. En pratique, on va rarement au-delà de 2 niveaux. Si ça devient difficile à lire, déstructurez en plusieurs étapes :

const { data } = apiResponse;
const { user, token } = data;
const { id, email } = user;

Même résultat, plus lisible.

Déstructuration de tableaux (en bref)

Les tableaux utilisent [] au lieu de {} :

const coordinates = [40.7128, -74.0060];

const [latitude, longitude] = coordinates;
// latitude = 40.7128, longitude = -74.0060

Ignorez des éléments avec des virgules :

const [first, , third] = ['a', 'b', 'c'];
// first = 'a', third = 'c'

L'opérateur de propagation avec les objets

L'opérateur de propagation (...) copie toutes les propriétés d'un objet dans un autre :

const baseUser = {
  role: 'member',
  isActive: true,
};

const adminUser = {
  ...baseUser,       // copie role et isActive
  email: 'admin@test.com',
  role: 'admin',    // écrase la valeur propagée
};

// { role: 'admin', isActive: true, email: 'admin@test.com' }

Créer des variantes de données de test

const defaultUser = {
  email: 'test@example.com',
  password: 'ValidPass1',
  role: 'member',
  isActive: true,
};

const adminUser    = { ...defaultUser, role: 'admin' };
const inactiveUser = { ...defaultUser, isActive: false };
const customEmail  = { ...defaultUser, email: 'custom@example.com' };

Ce pattern, "objet de base + surcharges", est très courant dans les fabriques de données de test. On définit l'état valide par défaut une seule fois et on le propage pour créer des variantes.

Patterns pratiques dans les tests Playwright

Déstructurer le body d'une réponse API

const response = await request.post('/api/users', {
  data: { email: 'new@test.com', password: 'ValidPass1' },
});

const { id, email, role, created_at } = await response.json();

expect(id).toBeTruthy();
expect(email).toBe('new@test.com');
expect(role).toBe('member');

Passer des paramètres objets aux helpers

async function fillLoginForm(page: Page, { email, password }: { email: string; password: string }) {
  await page.fill('[data-testid="email"]', email);
  await page.fill('[data-testid="password"]', password);
}

// Appel :
await fillLoginForm(page, { email: 'user@test.com', password: 'pass' });

Fusionner des configurations de test

const baseConfig = {
  baseURL: 'https://lab.becomeqa.com',
  timeout: 30000,
};

const ciConfig = {
  ...baseConfig,
  timeout: 60000,  // plus lent en CI
  video: 'retain-on-failure',
};

Erreurs fréquentes

Déstructurer depuis undefined :

const response = await fetch('/api/user');
const { id } = await response.json(); // Si response est null/undefined, ça plante

Toujours vérifier que la valeur existe avant de déstructurer des objets imbriqués profondément.

Modifier une copie propagée ne modifie pas l'original :

const original = { name: 'Alice', data: { score: 100 } };
const copy = { ...original };
copy.name = 'Bob';           // ✅ original.name reste 'Alice'
copy.data.score = 200;       // ⚠️ original.data.score change aussi !

La propagation est une copie superficielle. Les objets imbriqués restent des références partagées.

Récapitulatif

| Syntaxe | Ce qu'elle fait |

|---------|----------------|

| const { a, b } = obj | Extraire a et b depuis obj |

| const { a: x } = obj | Extraire a depuis obj, le nommer x |

| const { a = 5 } = obj | Extraire a, valeur par défaut 5 si absent |

| async ({ page, request }) => {} | Déstructurer les fixtures Playwright |

| { ...obj, key: 'value' } | Propager obj, surcharger ou ajouter key |

Les objets et la déstructuration sont omniprésents dans le JavaScript et TypeScript modernes. Le piège le plus courant : la propagation est superficielle. Modifier un objet imbriqué dans une copie propagée modifie aussi l'original, ce qui peut corrompre des données de test partagées entre plusieurs cas.

→ See also: JavaScript pour les QA Engineers: Le Minimum pour Commencer à Automatiser | Arrays JavaScript: map, filter, find et forEach — Le Guide de Terrain du QA | TypeScript pour QA: Pourquoi les Types Statiques Améliorent Vos Tests