mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
This hack dates all the way back to 2013:a2c4a78743Though it is convenient to reload the browser when server files change while running test-packages, that's not the behavior of most Meteor apps that use the autoupdate package, and this hack introduced a signficant difference in behavior between the test-in-browser and test-in-console driver packages, which finally surfaced due to the interaction between @toinevk's headless testing PR #9814 and my refactoring of the autoupdate package (fe9e4035f9). Tests should behave the same regardless of which driver package is used. It turns out there's a better way to make the browser reload each time the server restarts: simply modify Meteor.settings.public, since that object is included in the client hashes computed by the webapp package.
142 lines
4.8 KiB
JavaScript
142 lines
4.8 KiB
JavaScript
const manifestUrl = '/app.manifest';
|
|
|
|
function appcacheTest(name, cb) {
|
|
Tinytest.addAsync(`appcache - ${name}`, test => {
|
|
return fetch(manifestUrl).then(
|
|
res => cb(test, res),
|
|
err => test.fail(err)
|
|
);
|
|
});
|
|
}
|
|
|
|
|
|
// Verify that the code status of the HTTP response is "OK"
|
|
appcacheTest('presence', (test, manifest) =>
|
|
test.equal(manifest.status, 200, 'manifest not served'));
|
|
|
|
|
|
// Verify the content-type HTTP header
|
|
appcacheTest('content type', (test, manifest) =>
|
|
test.equal(manifest.headers.get('content-type'), 'text/cache-manifest'));
|
|
|
|
|
|
// Verify that each section header is only set once.
|
|
appcacheTest('sections uniqueness', async (test, manifest) => {
|
|
const content = await manifest.text();
|
|
const mandatorySectionHeaders = ['CACHE:', 'NETWORK:', 'FALLBACK:'];
|
|
const optionalSectionHeaders = ['SETTINGS'];
|
|
const allSectionHeaders = [
|
|
...mandatorySectionHeaders,
|
|
...optionalSectionHeaders.filter(
|
|
header => !mandatorySectionHeaders.includes(header)
|
|
),
|
|
];
|
|
allSectionHeaders.forEach(sectionHeader => {
|
|
const globalSearch = new RegExp(sectionHeader, "g");
|
|
const matches = content.match(globalSearch) || [];
|
|
test.isTrue(matches.length <= 1, `${sectionHeader} is set twice`);
|
|
if (mandatorySectionHeaders.includes(sectionHeader)) {
|
|
test.isTrue(matches.length == 1, `${sectionHeader} is not set`);
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
// Verify the content of the header and of each section of the manifest using
|
|
// regular expressions. Regular expressions matches malformed URIs but that's
|
|
// not what we're trying to catch here (the user is free to add its own content
|
|
// in the manifest -- even malformed).
|
|
appcacheTest('sections validity', async (test, manifest) => {
|
|
const lines = (await manifest.text()).split('\n');
|
|
let i = 0;
|
|
let currentRegex = null;
|
|
let line = null;
|
|
|
|
const nextLine = () => lines[i++];
|
|
|
|
const eof = () => i >= lines.length;
|
|
|
|
const nextLineMatches = (expected, n) => {
|
|
n = n || 1;
|
|
for(let j = 0; j < n; j++) {
|
|
const testFunc = toString.call(expected) === '[object RegExp]' ?
|
|
'matches' :
|
|
'equal';
|
|
test[testFunc](nextLine(), expected);
|
|
}
|
|
};
|
|
|
|
// Verify header validity
|
|
nextLineMatches('CACHE MANIFEST');
|
|
nextLineMatches('');
|
|
nextLineMatches(/^# [a-z0-9]+$/i);
|
|
nextLineMatches('');
|
|
|
|
// Verify body validity
|
|
while (! eof()) {
|
|
line = nextLine();
|
|
|
|
// There are three distinct sections: 'CACHE', 'FALLBACK', and 'NETWORK'.
|
|
// A section start with its name suffixed by a colon. When we read a new
|
|
// section header, we update the currentRegex expression for the next lines
|
|
// of the section.
|
|
// XXX There is also a 'SETTINGS' section, not used by this package. If this
|
|
// section is used, the test will fail.
|
|
if (line === 'CACHE:' || line === 'NETWORK:')
|
|
currentRegex = /^\S+$/;
|
|
|
|
else if (line === 'FALLBACK:')
|
|
currentRegex = /^\S+ \S+$/;
|
|
|
|
// Blank lines and lines starting with a `#` (comments) are valid
|
|
else if (line == '' || line.match(/^#.+/))
|
|
continue;
|
|
|
|
// Outside sections, only blanks lines and comments are valid
|
|
else if (currentRegex === null)
|
|
test.fail(`Invalid line ${i}: ${line}`);
|
|
|
|
// Inside a section, a star is a valid expression
|
|
else if (line === '*')
|
|
continue;
|
|
|
|
// If it is not a blank line, not a comment, and not a header it must
|
|
// match the current section format
|
|
else
|
|
test.matches(line, currentRegex, `line ${i}`);
|
|
}
|
|
});
|
|
|
|
|
|
// Verify that resources declared on the server with the `onlineOnly` parameter
|
|
// are present in the network section of the manifest. The `appcache` package
|
|
// also automatically add the manifest (`app.manifest`) add the star symbol to
|
|
// this list and therefore we also check the presence of these two elements.
|
|
appcacheTest('network section content', async (test, manifest) => {
|
|
const shouldBePresentInNetworkSection = [
|
|
"/app.manifest",
|
|
"/online/",
|
|
"/bigimage.jpg",
|
|
"/largedata.json",
|
|
"*"
|
|
];
|
|
const lines = (await manifest.text()).split('\n');
|
|
const startNetworkSection = lines.indexOf('NETWORK:');
|
|
|
|
// We search the end of the 'NETWORK:' section by looking at the beginning
|
|
// of any potential other section. By default we set this value to
|
|
// `lines.length - 1` which is the index of the last line.
|
|
const otherSections = ['CACHE:', 'FALLBACK:', 'SETTINGS'];
|
|
const endNetworkSection = otherSections.reduce((min, sectionName) => {
|
|
const position = lines.indexOf(sectionName);
|
|
return position > startNetworkSection && position < min ? position : min;
|
|
}, lines.length - 1);
|
|
|
|
// We remove the first line because it's the 'NETWORK:' header line.
|
|
const networkLines = lines.slice(startNetworkSection + 1, endNetworkSection);
|
|
|
|
shouldBePresentInNetworkSection.forEach(
|
|
item => test.include(networkLines, item)
|
|
);
|
|
});
|