react-native-svg-app-icon
Version:
App icon generator for React Native projects
155 lines (129 loc) • 6.57 kB
JavaScript
var fse = _interopRequireWildcard(require("fs-extra"));
var _globPromise = _interopRequireDefault(require("glob-promise"));
var path = _interopRequireWildcard(require("path"));
var _pixelmatch = _interopRequireDefault(require("pixelmatch"));
var _sharp = _interopRequireDefault(require("sharp"));
var tmp = _interopRequireWildcard(require("tmp"));
var index = _interopRequireWildcard(require("../index"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
describe("index", () => {
const fixturesPath = path.join(__dirname, "fixtures");
const defaultConfig = {
icon: {
backgroundPath: path.join(fixturesPath, "example", "icon-background.svg"),
foregroundPath: path.join(fixturesPath, "example", "icon.svg")
},
platforms: ["android", "ios"],
force: false
};
let tmpDir;
beforeEach(() => {
tmpDir = tmp.dirSync({
unsafeCleanup: true
});
process.chdir(tmpDir.name);
});
afterEach(() => {
tmpDir.removeCallback();
});
it("generates files from example matching fixtures", () => testFixture("example", 0.16));
it("generates files from empty matching fixtures", () => testFixture("empty", 0.06));
it("generates files from text matching fixtures", () => testFixture("text", 0.12), 20 * 1000);
it("determines the correct ios asset path", async () => {
await fse.ensureDir(path.join("ios", "project", "Images.xcassets"));
const generator = index.generate(defaultConfig);
const generatedFiles = await readIterable(generator);
expect(generatedFiles).toContain("ios/project/Images.xcassets/AppIcon.appiconset/iphone-40@3x.png");
});
it("does not re-render files on second run", async () => {
await fse.ensureDir(path.join("ios", "project", "Images.xcassets"));
const firstRunFiles = await readIterable(index.generate(defaultConfig));
const sedonRunFiles = await readIterable(index.generate(defaultConfig));
expect(firstRunFiles.length).toBeGreaterThan(0);
expect(sedonRunFiles.length).toBe(0);
});
it("does re-renders files on second run when force is set to true", async () => {
await fse.ensureDir(path.join("ios", "project", "Images.xcassets"));
const firstRunFiles = await readIterable(index.generate(defaultConfig));
const sedonRunFiles = await readIterable(index.generate({ ...defaultConfig,
force: true
}));
expect(firstRunFiles.length).toBeGreaterThan(0);
expect(sedonRunFiles.length).toBeGreaterThan(0);
});
async function testFixture(fixture, threshold) {
const fixtureDir = path.join(fixturesPath, fixture);
const generator = index.generate({ ...defaultConfig,
icon: {
backgroundPath: (await fse.pathExists(path.join(fixtureDir, "icon-background.svg"))) ? path.join(fixtureDir, "icon-background.svg") : undefined,
foregroundPath: path.join(fixtureDir, "icon.svg")
},
androidOutputPath: path.join(tmpDir.name, "android", "app", "src", "main", "res"),
iosOutputPath: path.join(tmpDir.name, "ios", fixture, "Images.xcassets", "AppIcon.appiconset")
});
const generatedFiles = [];
for await (const file of generator) {
const localPath = path.relative(tmpDir.name, file);
const fixturePath = path.join(fixtureDir, localPath);
await expectFilesToEqual(file, fixturePath, threshold);
generatedFiles.push(localPath);
}
expect(generatedFiles.sort()).toEqual((await (0, _globPromise.default)("*/**", {
cwd: fixtureDir,
nodir: true
})).sort());
}
});
async function readIterable(iterable) {
const values = [];
for await (const value of iterable) {
values.push(value);
}
return values;
}
async function expectFilesToEqual(expected, actual, threshold) {
await expectFileToExist(expected);
await expectFileToExist(actual);
const extension = path.extname(expected);
switch (extension) {
case ".png":
return expectImagesToEqual(expected, actual, threshold);
case ".json":
return expectJsonToEqual(expected, actual);
case ".xml":
return expectXmlToEqual(expected, actual);
default:
throw Error(`Unsupported comparison file type ${extension}`);
}
}
async function expectFileToExist(path) {
if (!(await fse.pathExists(path))) {
throw Error(`File did not exist: ${path}`);
}
}
async function expectXmlToEqual(expected, actual) {
// TODO: Compare XML structure
expect(await fse.readFile(expected, "utf-8")).toEqual(await fse.readFile(actual, "utf-8"));
}
async function expectJsonToEqual(expected, actual) {
expect(await fse.readJson(expected)).toEqual(await fse.readJson(actual));
}
async function expectImagesToEqual(expected, actual, threshold) {
const expectedImage = (0, _sharp.default)(expected);
const actualImage = (0, _sharp.default)(actual);
const expectedData = await expectedImage.ensureAlpha().raw().toBuffer({
resolveWithObject: true
});
const actualData = await actualImage.ensureAlpha().raw().toBuffer({
resolveWithObject: true
});
expect(actualData.info).toEqual(expectedData.info);
const totalPixelCount = expectedData.info.width * expectedData.info.height;
const mismatchingPixelCount = (0, _pixelmatch.default)(expectedData.data, actualData.data, null, expectedData.info.width, expectedData.info.height, {
threshold
});
expect(mismatchingPixelCount / totalPixelCount).toBeLessThanOrEqual(threshold);
}
;