Repository: eslint/eslint
File: lib/rule-tester/rule-tester.js (JavaScript)

Code before:
                                                `${suggestionPrefix} Test can not use 'messageId' if rule under test doesn't define 'meta.messages'.`
                                            );
                                            assert.ok(
                                                hasOwnProperty(rule.meta.messages, expectedSuggestion.messageId),
                                                `${suggestionPrefix} Test has invalid messageId '${expectedSuggestion.messageId}', the rule under test allows only one of ${friendlyIDList}.`
                                            );
                                            assert.strictEqual(
                                                actualSuggestion.messageId,
                                                expectedSuggestion.messageId,
                                                `${suggestionPrefix} messageId should be '${expectedSuggestion.messageId}' but got '${actualSuggestion.messageId}' instead.`
                                            );
                                            if (hasOwnProperty(expectedSuggestion, "data")) {
                                                const unformattedMetaMessage = rule.meta.messages[expectedSuggestion.messageId];
                                                const rehydratedDesc = interpolate(unformattedMetaMessage, expectedSuggestion.data);

                                                assert.strictEqual(
                                                    actualSuggestion.desc,
                                                    rehydratedDesc,
                                                    `${suggestionPrefix} Hydrated test desc "${rehydratedDesc}" does not match received desc "${actualSuggestion.desc}".`
                                                );
                                            } else {
                                                const missing = getMissingMessagePlaceholders(actualSuggestion.desc);

                                                assert.ok(
                                                    missing.length === 0,
                                                    `The message of the suggestion has missing placeholders: ${missing.join(", ")}. Please provide them via the 'data' property for the suggestion in the context.report call`
                                                );
                                            }
                                        } else if (hasOwnProperty(expectedSuggestion, "data")) {
                                            assert.fail(
                                                `${suggestionPrefix} Test must specify 'messageId' if 'data' is used.`
                                            );
                                        } else {
                                            assert.fail(
                                                `${suggestionPrefix} Test must specify either 'messageId' or 'desc'.`
                                            );
                                        }

                                        assert.ok(hasOwnProperty(expectedSuggestion, "output"), `${suggestionPrefix} The "output" property is required.`);
                                        const codeWithAppliedSuggestion = SourceCodeFixer.applyFixes(item.code, [actualSuggestion]).output;

                                        // Verify if suggestion fix makes a syntax error or not.
                                        const errorMessageInSuggestion =
                                                linter.verify(codeWithAppliedSuggestion, result.configs, result.filename).find(m => m.fatal);

                                        assert(!errorMessageInSuggestion, [
                                            "A fatal parsing error occurred in suggestion fix.",
                                            `Error: ${errorMessageInSuggestion && errorMessageInSuggestion.message}`,
                                            "Suggestion output:",
                                            codeWithAppliedSuggestion
                                        ].join("\n"));

Review comment (suggestion):
```suggestion
                                                    `The message of the suggestion has missing placeholders: ${missing.join(", ")}. Please provide them via the 'data' property for the suggestion in the context.report() call.`
```

Code after:
                                        );
                                        Object.keys(expectedSuggestion).forEach(propertyName => {
                                            assert.ok(
                                                suggestionObjectParameters.has(propertyName),
                                                `Invalid suggestion property name '${propertyName}'. Expected one of ${friendlySuggestionObjectParameterList}.`
                                            );
                                        });

                                        const actualSuggestion = message.suggestions[index];
                                        const suggestionPrefix = `Error Suggestion at index ${index}:`;

                                        if (hasOwnProperty(expectedSuggestion, "desc")) {
                                            assert.ok(
                                                !hasOwnProperty(expectedSuggestion, "data"),
                                                `${suggestionPrefix} Test should not specify both 'desc' and 'data'.`
                                            );
                                            assert.ok(
                                                !hasOwnProperty(expectedSuggestion, "messageId"),
                                                `${suggestionPrefix} Test should not specify both 'desc' and 'messageId'.`
                                            );
                                            assert.strictEqual(
                                                actualSuggestion.desc,
                                                expectedSuggestion.desc,
                                                `${suggestionPrefix} desc should be "${expectedSuggestion.desc}" but got "${actualSuggestion.desc}" instead.`
                                            );
                                        } else if (hasOwnProperty(expectedSuggestion, "messageId")) {
                                            assert.ok(
                                                ruleHasMetaMessages,
                                                `${suggestionPrefix} Test can not use 'messageId' if rule under test doesn't define 'meta.messages'.`
                                            );
                                            assert.ok(
                                                hasOwnProperty(rule.meta.messages, expectedSuggestion.messageId),
                                                `${suggestionPrefix} Test has invalid messageId '${expectedSuggestion.messageId}', the rule under test allows only one of ${friendlyIDList}.`
                                            );
                                            assert.strictEqual(
                                                actualSuggestion.messageId,
                                                expectedSuggestion.messageId,
                                                `${suggestionPrefix} messageId should be '${expectedSuggestion.messageId}' but got '${actualSuggestion.messageId}' instead.`
                                            );

                                            const unsubstitutedPlaceholders = getUnsubstitutedMessagePlaceholders(
                                                actualSuggestion.desc,
                                                rule.meta.messages[expectedSuggestion.messageId],
                                                expectedSuggestion.data
                                            );

                                            assert.ok(
                                                unsubstitutedPlaceholders.length === 0,
                                                `The message of the suggestion has ${unsubstitutedPlaceholders.length > 1 ? `unsubstituted placeholders: ${unsubstitutedPlaceholders.map(name => `'${name}'`).join(", ")}` : `an unsubstituted placeholder '${unsubstitutedPlaceholders[0]}'`}. Please provide the missing ${unsubstitutedPlaceholders.length > 1 ? "values" : "value"} via the 'data' property for the suggestion in the context.report() call.`
                                            );