Postman — популярный инструмент для тестирования API. Однако при тестировании такого API, как Optimizely Graph, который я буду использовать во внешнем интерфейсе, я предпочитаю делать это с помощью JS + Fetch.
Это позволяет мне выявить любые особенности использования API в JavaScript. Затем код можно передать команде фронтенда для использования в соответствующей платформе, а результаты JSON можно сохранить для макетных данных Storybook.
Пример
import projectConfig from "../../CMS12/appsettings.json" assert { type: "json" };
// Define the GraphQL query to fetch StandardPages in the "Acme" category with their associated form templates
const formQuery =
`fragment FormContainerBlock on FormContainerBlock { __typename FormRenderTemplate }
query MyQuery {
StandardPage( where: { PrimaryCategory: { Name: { eq: "Acme" } } } )
{ items { Name Url MainContent { ContentLink { Expanded { ...FormContainerBlock } } } } }
}`
// Wrap the query in the expected JSON structure for the Content Graph API Request Body
const queryWrapper = `{"query":${JSON.stringify(formQuery)}}`;
// Public key access - Review security implications before using outside of local development
const publicKey = projectConfig.Optimizely.ContentGraph.SingleKey;
const graphUrl = `https://cg.optimizely.com/content/v2?auth=${publicKey}`;
const outputData = (data) => {
const formPages = data.StandardPage.items
.map(i => {
return {
name: i.Name,
url: i.Url,
forms: i.MainContent
.filter(b => b.ContentLink.Expanded.FormRenderTemplate)
.map(b => b.ContentLink.Expanded.FormRenderTemplate)
};
})
.filter(i => i.forms?.length);
formPages.forEach(page => page.forms.forEach(f => console.log(f)));
}
const executeQuery = async () => {
return fetch(graphUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: queryWrapper
})
.then((response) => {
if (response.status >= 400) {
throw new Error(`Error fetching data`, {cause: response});
} else {
return response.json();
}
})
.then((data) => outputData(data.data))
.catch(async error => {
if (error.cause.status === 400) {
// Graph returns JSON on most errors. Normally this is caused by a query syntax error.
const result = await error.cause.json();
console.log(`CODE: ${result.code}`);
console.log(`DETAILS:n${JSON.stringify(result.details)}`);
}
})
}
const result = await executeQuery();
console.log("Completed");
Перейти к авария
Как бежать
Прежде всего, есть некоторые предпосылки:
- Доступ к индексу Optimizely Graph.
- Запросите индекс разработчика.
Для этого примера нам нужен только открытый ключ.
Как отлаживать VS Code
Мы можем настроить VS Code для отладки JavaScript. Это дает нам обычный доступ к переменным для проверки и просмотра.
Отладка текущего файла
Его следует добавить в файл launch.json в папке .vscode в корне исходного кода. Это позволяет запускать и отлаживать просматриваемый в данный момент файл JavaScript.
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Current Opened File",
"program": "${file}"
}
]
}
Если вы используете интерфейсную платформу, вам обычно потребуется запустить платформу и подключить отладку, используя стандартную конфигурацию.
Авария
Итак, я расскажу, что происходит в этом коде.
Настройки и переменные
import projectConfig from "../../CMS12/appsettings.json" assert { type: "json" };
// Define the GraphQL query to fetch StandardPages in the "Acme" category with their associated form templates
const formQuery =
`fragment FormContainerBlock on FormContainerBlock { __typename FormRenderTemplate }
query MyQuery {
StandardPage( where: { PrimaryCategory: { Name: { eq: "Acme" } } } )
{ items { Name Url MainContent { ContentLink { Expanded { ...FormContainerBlock } } } } }
}`
// Wrap the query in the expected JSON structure for the Content Graph API Request Body
const queryWrapper = `{"query":${JSON.stringify(formQuery)}}`;
// Public key access - Review security implications before using outside of local development
const publicKey = projectConfig.Optimizely.ContentGraph.SingleKey;
const graphUrl = `https://cg.optimizely.com/content/v2?auth=${publicKey}`;
Сначала я импортирую файл конфигурации из проекта, который содержит обычные настройки Optimizely Graph. Если у вас несколько конфигураций, вам понадобится выбрать одну из них с настройками разработчика.
Затем у нас есть запрос GraphQL. Это можно скопировать и вставить со страницы GraphiQL. Этот пример запроса находит блоки формы в основном содержимом страницы стандартного типа. Это было написано для БЕТА-версии Headless Forms, в которой данные формы вложены в свойство блока контейнера формы.
Оболочка создает стандартное тело запроса, которое ожидает Optimizely Graph.
Наконец, мы извлекаем единственный ключ из общей конфигурации и создаем URL-адрес.
ВНИМАНИЕ: См. проблемы безопасности
Функция рендеринга
const outputData = (data) => {
const formPages = data.StandardPage.items
.map(i => {
return {
name: i.Name,
url: i.Url,
forms: i.MainContent
.filter(b => b.ContentLink.Expanded.FormRenderTemplate)
.map(b => b.ContentLink.Expanded.FormRenderTemplate)
};
})
.filter(i => i.forms?.length);
formPages.forEach(page => page.forms.forEach(f => console.log(f)));
}
Эта функция обрабатывает данные результатов графика. Поскольку мы работаем на JavaScript и результаты представляют собой JSON, мы можем работать с этим динамически. Используя отладчик, мы можем проверить структуру данных и получить к ней доступ по мере необходимости. В этом примере я детализирую FromRenderTemplate. В бета-версии Headless Forms это был блок JSON, содержащий все элементы формы и настройки формы.
Для тестирования я обычно вывожу данные на консоль, которая отображается в VS Code. Я бы поэкспериментировал с отображением данных здесь, используя JSON.stringify() для вывода данных на консоль или просмотра через инспектор отладчика.
Выборка -> Затем -> Функция перехвата цепочки
const executeQuery = async () => {
return fetch(graphUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: queryWrapper
})
.then((response) => {
if (response.status >= 400) {
throw new Error(`Error fetching data`, {cause: response});
} else {
return response.json();
}
})
.then((data) => outputData(data.data))
.catch(async error => {
if (error.cause.status === 400) {
// Graph returns JSON on most errors. Normally this is caused by a query syntax error.
const result = await error.cause.json();
console.log(`CODE: ${result.code}`);
console.log(`DETAILS:n${JSON.stringify(result.details)}`);
}
})
}
Это довольно стандартная цепочка вызовов API. Если вы прекратите отладку, это будет очень просто, но во время экспериментов мы будем получать синтаксические ошибки GraphQL, поэтому они обнаруживаются и регистрируются.
Принести
fetch отправляет вызов POST с упакованным запросом на общедоступный URL-адрес. Если вы защитили свой индекс Graph, вам также потребуется добавить заголовок аутентификации в вызов Fetch.
Например:
return fetch(graphUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${projectConfig.Authorization_Token}`
},
body: queryWrapper
})
Если вы работаете с API, который имеет отдельный вызов для запроса авторизации, выполните этот вызов Fetch, извлеките токен и перейдите к основному вызову Fetch. В рабочем коде вам понадобится кэшировать ключ в зависимости от срока действия, указанного в API.
Потом – Ответ
Первый then проверяет код состояния. Большинство API возвращают данные по ответам 4xx, но зачастую это формат, отличный от рабочего ответа. Итак, здесь мы вызываем ошибку, чтобы иметь возможность обработать ее отдельно.
response.JSON() хватает тело на путь успеха.
Затем – Данные
Здесь мы делегируем данные функции вывода.
Ловить
В catch мы ожидаем прочитать ошибки GraphQL, поэтому записываем данные на консоль.
Краткое содержание
Этот процесс можно использовать для любого API, который вы будете использовать во внешнем интерфейсе.
Хорошим примером является график, поскольку как запросы, так и ответы на данные могут быть сложными и многословными. Прежде чем вы достигнете ожидаемых свойств, вы обнаружите, что вложенные данные имеют несколько оболочек. Тестируя с помощью JS, вы также можете увидеть, как недостающие данные влияют на их использование.
Следующие шаги
В следующий раз я расширю это объяснение на TypeScript с помощью простых типов, которые позволяют динамическую обработку дочерних объектов в данных и строгую типизацию для рендеринга в шаблонах.
Ссылки
Вопросы безопасности
Обратите внимание, что многие производственные реализации захотят контролировать и запутывать доступ к данным графа. Это можно сделать несколькими способами. Например, нажатие клавиш и доступ к Graph к компонентам сервера или SSG к странице или сайту.
04 февраля 2026 г.
Читайте также
