142 lines
5.0 KiB
HTTP
142 lines
5.0 KiB
HTTP
# Chatbot content feed (see .ddev/plans/CHATBOT-MCP-01-TYPO3-CONTENT-FEED.md)
|
|
#
|
|
# Pick the "local" environment in PhpStorm and run the whole file top to bottom: the manifest
|
|
# request stores uids and a content URL that the later requests use.
|
|
#
|
|
# Needs, locally:
|
|
# - http-client.private.env.json with {"local": {"cmsApiKey": "<your key>"}} (gitignored)
|
|
# - the same key in TYPO3, e.g.
|
|
# ddev exec vendor/bin/typo3cms configuration:set EXTENSIONS/ep_products/cmsApiKey <your key>
|
|
# plus contentFeedSites etc. - or open and save the ep_products extension configuration once
|
|
# in the backend, which writes all the defaults.
|
|
#
|
|
# The kill switch (contentFeedEnabled = 0) cannot be toggled from here; with it off, every keyed
|
|
# request below answers 503.
|
|
|
|
### Manifest without a key is refused
|
|
GET {{host}}/api/content/manifest
|
|
|
|
> {%
|
|
client.test("403 without key", function () {
|
|
client.assert(response.status === 403, "expected 403, got " + response.status);
|
|
});
|
|
%}
|
|
|
|
### Manifest
|
|
GET {{host}}/api/content/manifest
|
|
X-Api-Key: {{cmsApiKey}}
|
|
|
|
> {%
|
|
client.test("manifest is complete and well-formed", function () {
|
|
client.assert(response.status === 200, "expected 200, got " + response.status);
|
|
client.assert(response.body.items.length > 0, "manifest is empty");
|
|
client.assert(response.body.sites.length > 0, "no sites");
|
|
client.assert(
|
|
response.body.items.every(function (item) { return item.type && item.uid && item.modified; }),
|
|
"an item lacks type, uid or modified"
|
|
);
|
|
});
|
|
|
|
var uidsOf = function (type, limit) {
|
|
return response.body.items
|
|
.filter(function (item) { return item.type === type; })
|
|
.slice(0, limit)
|
|
.map(function (item) { return item.uid; })
|
|
.join(",");
|
|
};
|
|
|
|
client.global.set("productUids", uidsOf("product", 5));
|
|
client.global.set("hotelUids", uidsOf("hotel", 5));
|
|
client.global.set("regionUids", uidsOf("region", 5));
|
|
client.global.set("newsUids", uidsOf("news", 3));
|
|
|
|
var page = response.body.items.filter(function (item) { return item.type === "page" && item.contentUrl; })[0];
|
|
client.global.set("contentUrl", page.contentUrl);
|
|
|
|
var tooMany = [];
|
|
for (var i = 1; i <= 101; i++) { tooMany.push(i); }
|
|
client.global.set("tooManyUids", tooMany.join(","));
|
|
%}
|
|
|
|
### Products (with FAQs)
|
|
GET {{host}}/api/content/records?type=product&uids={{productUids}}
|
|
X-Api-Key: {{cmsApiKey}}
|
|
|
|
> {%
|
|
client.test("every requested product comes back, links resolved", function () {
|
|
client.assert(response.status === 200, "expected 200, got " + response.status);
|
|
client.assert(response.body.items.length === client.global.get("productUids").split(",").length, "products missing");
|
|
client.assert(JSON.stringify(response.body).indexOf("t3://") === -1, "unresolved t3:// link");
|
|
});
|
|
%}
|
|
|
|
### Hotels (codes include matchcode aliases)
|
|
GET {{host}}/api/content/records?type=hotel&uids={{hotelUids}}
|
|
X-Api-Key: {{cmsApiKey}}
|
|
|
|
> {%
|
|
client.test("hotels carry their codes", function () {
|
|
client.assert(response.status === 200, "expected 200, got " + response.status);
|
|
client.assert(response.body.items.every(function (hotel) { return Array.isArray(hotel.codes); }), "hotel without codes");
|
|
});
|
|
%}
|
|
|
|
### Regions
|
|
GET {{host}}/api/content/records?type=region&uids={{regionUids}}
|
|
X-Api-Key: {{cmsApiKey}}
|
|
|
|
### Blog articles
|
|
GET {{host}}/api/content/records?type=news&uids={{newsUids}}
|
|
X-Api-Key: {{cmsApiKey}}
|
|
|
|
### Unknown type is a 400
|
|
GET {{host}}/api/content/records?type=page&uids=1
|
|
X-Api-Key: {{cmsApiKey}}
|
|
|
|
> {%
|
|
client.test("400 for unknown type", function () {
|
|
client.assert(response.status === 400, "expected 400, got " + response.status);
|
|
});
|
|
%}
|
|
|
|
### More than 100 uids is a 400
|
|
GET {{host}}/api/content/records?type=product&uids={{tooManyUids}}
|
|
X-Api-Key: {{cmsApiKey}}
|
|
|
|
> {%
|
|
client.test("400 above 100 uids", function () {
|
|
client.assert(response.status === 400, "expected 400, got " + response.status);
|
|
});
|
|
%}
|
|
|
|
### Content-only render of the first page in the manifest
|
|
GET {{contentUrl}}
|
|
X-Api-Key: {{cmsApiKey}}
|
|
|
|
> {%
|
|
client.test("bare article, never cached by proxies", function () {
|
|
client.assert(response.status === 200, "expected 200, got " + response.status);
|
|
client.assert(response.body.indexOf("<article>") === 0, "not a bare <article> fragment");
|
|
client.assert(response.headers.valueOf("Cache-Control") === "private, no-store", "unexpected Cache-Control");
|
|
});
|
|
%}
|
|
|
|
### Content-only render without a key is a 404 (the type must not be discoverable)
|
|
GET {{contentUrl}}
|
|
|
|
> {%
|
|
client.test("404 without key", function () {
|
|
client.assert(response.status === 404, "expected 404, got " + response.status);
|
|
});
|
|
%}
|
|
|
|
### Content-only render with a wrong key is a 404
|
|
GET {{contentUrl}}
|
|
X-Api-Key: definitely-wrong
|
|
|
|
> {%
|
|
client.test("404 with wrong key", function () {
|
|
client.assert(response.status === 404, "expected 404, got " + response.status);
|
|
});
|
|
%}
|