-
-
Notifications
You must be signed in to change notification settings - Fork 929
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
sergesemashko
committed
Mar 8, 2017
1 parent
16e8cc7
commit 556168c
Showing
10 changed files
with
365 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/* This file will not cause a linting error */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
"use strict" | ||
|
||
const path = require("path") | ||
const standalone = require("../standalone") | ||
const hash = require("../utils/hash") | ||
const fixturesPath = path.join(__dirname, "fixtures") | ||
const fsExtra = require("fs-promise") | ||
const fileExists = require("file-exists-promise") | ||
|
||
const cwd = process.cwd() | ||
const invalidFile = path.join(fixturesPath, "empty-block.css") | ||
const validFile = path.join(fixturesPath, "cache", "valid.css") | ||
const newFileDest = path.join(fixturesPath, "cache", "newFile.css") | ||
|
||
// Config object is getting mutated internally. | ||
// Return new object of the same structure to | ||
// make sure config doesn't change between runs. | ||
function getConfig() { | ||
return { | ||
files: path.join(fixturesPath, "cache", "*.css"), | ||
config: { | ||
rules: { "block-no-empty": true, "color-no-invalid-hex": true }, | ||
}, | ||
cache: true, | ||
} | ||
} | ||
|
||
describe("standalone cache", () => { | ||
const expectedCacheFilePath = path.join(cwd, ".stylelintcache") | ||
|
||
beforeEach(() => { | ||
// Initial run to warm up the cache | ||
return standalone(getConfig()) | ||
}) | ||
|
||
afterEach(() => { | ||
// Clean up after each test case | ||
return Promise.all([ | ||
fsExtra.remove(expectedCacheFilePath), | ||
fsExtra.remove(newFileDest), | ||
]) | ||
}) | ||
|
||
it("cache file is created at $CWD/.stylelintcache", () => { | ||
// Ensure cache file exists | ||
return fileExists(expectedCacheFilePath).then(isFileExist => { | ||
expect(!!isFileExist).toBe(true) | ||
return fsExtra.readJson(expectedCacheFilePath) | ||
}).then(cacheFile => { | ||
// Ensure cache file contains only linted css file | ||
expect(typeof cacheFile[validFile] === "object").toBe(true) | ||
expect(typeof cacheFile[newFileDest] === "undefined").toBe(true) | ||
}) | ||
}) | ||
|
||
it("only changed files are linted", () => { | ||
// Add "changed" file | ||
return fsExtra.copy(validFile, newFileDest).then(() => { | ||
// Next run should lint only changed files | ||
return standalone(getConfig()) | ||
}).then(output => { | ||
// Ensure only changed files are linted | ||
const isValidFileLinted = !!output.results.find(file => file.source === validFile) | ||
const isNewFileLinted = !!output.results.find(file => file.source === newFileDest) | ||
expect(isValidFileLinted).toBe(false) | ||
expect(isNewFileLinted).toBe(true) | ||
// Ensure cache file contains linted css files | ||
return fsExtra.readJson(expectedCacheFilePath) | ||
}).then(cachedFiles => { | ||
expect(typeof cachedFiles[validFile] === "object").toBe(true) | ||
expect(typeof cachedFiles[newFileDest] === "object").toBe(true) | ||
}) | ||
}) | ||
|
||
it("all files are linted on config change", () => { | ||
const changedConfig = getConfig() | ||
changedConfig.config.rules["block-no-empty"] = false | ||
return fsExtra.copy(validFile, newFileDest).then(() => { | ||
// All file should be re-linted as config has changed | ||
return standalone(changedConfig) | ||
}).then(output => { | ||
// Ensure all files are re-linted | ||
const isValidFileLinted = !!output.results.find(file => file.source === validFile) | ||
const isNewFileLinted = !!output.results.find(file => file.source === newFileDest) | ||
expect(isValidFileLinted).toBe(true) | ||
expect(isNewFileLinted).toBe(true) | ||
}) | ||
}) | ||
|
||
it("invalid files are not cached", () => { | ||
return fsExtra.copy(invalidFile, newFileDest).then(() => { | ||
// Should lint only changed files | ||
return standalone(getConfig()) | ||
}).then((output) => { | ||
expect(output.errored).toBe(true) | ||
// Ensure only changed files are linted | ||
const isValidFileLinted = !!output.results.find(file => file.source === validFile) | ||
const isInvalidFileLinted = !!output.results.find(file => file.source === newFileDest) | ||
expect(isValidFileLinted).toBe(false) | ||
expect(isInvalidFileLinted).toBe(true) | ||
// Ensure cache file doesn't contain invalid file | ||
return fsExtra.readJsonSync(expectedCacheFilePath) | ||
}).then(cachedFiles => { | ||
expect(typeof cachedFiles[validFile] === "object").toBe(true) | ||
expect(typeof cachedFiles[newFileDest] === "undefined").toBe(true) | ||
}) | ||
}) | ||
it("cache file is removed when cache is disabled", () => { | ||
const noCacheConfig = getConfig() | ||
|
||
noCacheConfig.cache = false | ||
let cacheFileExists = true | ||
return standalone(noCacheConfig).then(() => { | ||
return fileExists(expectedCacheFilePath).then(() => { | ||
throw new Error(`Cache file is supposed to be removed, ${expectedCacheFilePath} is found instead`) | ||
}).catch(() => { | ||
cacheFileExists = false | ||
expect(cacheFileExists).toBe(false) | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe("standalone cache uses cacheLocation", () => { | ||
const cacheLocationFile = path.join(fixturesPath, "cache", ".cachefile") | ||
const cacheLocationDir = path.join(fixturesPath, "cache") | ||
const expectedCacheFilePath = path.join(cacheLocationDir, `.stylelintcache_${hash(cwd)}`) | ||
afterEach(() => { | ||
// clean up after each test | ||
return Promise.all([ | ||
fsExtra.remove(expectedCacheFilePath), | ||
fsExtra.remove(cacheLocationFile), | ||
]) | ||
}) | ||
it("cacheLocation is a file", () => { | ||
const config = getConfig() | ||
config.cacheLocation = cacheLocationFile | ||
return standalone(config).then(() => { | ||
// Ensure cache file is created | ||
return fileExists(cacheLocationFile) | ||
}).then(fileStats => { | ||
expect(!!fileStats).toBe(true) | ||
// Ensure cache file contains cached entity | ||
return fsExtra.readJson(cacheLocationFile) | ||
}).then(cacheFile => { | ||
expect(typeof cacheFile[validFile] === "object").toBe(true) | ||
}) | ||
}) | ||
it("cacheLocation is a directory", () => { | ||
const config = getConfig() | ||
config.cacheLocation = cacheLocationDir | ||
return standalone(config).then(() => { | ||
return fileExists(expectedCacheFilePath) | ||
}).then(cacheFileStats => { | ||
// Ensure cache file is created | ||
expect(!!cacheFileStats).toBe(true) | ||
// Ensure cache file contains cached entity | ||
return fsExtra.readJson(expectedCacheFilePath) | ||
}).then(cacheFile => { | ||
expect(typeof cacheFile[validFile] === "object").toBe(true) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* @flow */ | ||
"use strict" | ||
|
||
const fileEntryCache = require("file-entry-cache") | ||
const path = require("path") | ||
const debug = require("debug")("stylelint:file-cache") | ||
const getCacheFile = require("./getCacheFile") | ||
|
||
const DEFAULT_CACHE_LOCATION = "./.stylelintcache" | ||
const DEFAULT_HASH = "" | ||
|
||
function FileCache(cacheLocation/*: String */, hashOfConfig/*: ?String */) { | ||
const cacheFile = path.resolve(getCacheFile(cacheLocation || DEFAULT_CACHE_LOCATION, process.cwd())) | ||
debug(`Cache file is created at ${cacheFile}`) | ||
this._fileCache = fileEntryCache.create(cacheFile) | ||
this._hashOfConfig = hashOfConfig || DEFAULT_HASH | ||
} | ||
|
||
FileCache.prototype.hasFileChanged = function (absoluteFilepath) { | ||
// Get file descriptor compares current metadata against cached | ||
// one and stores the result to "changed" prop. | ||
const descriptor = this._fileCache.getFileDescriptor(absoluteFilepath) | ||
const meta = descriptor.meta || {} | ||
const changed = descriptor.changed || meta.hashOfConfig !== this._hashOfConfig | ||
if (!changed) { | ||
debug(`Skip linting ${absoluteFilepath}. File hasn't changed.`) | ||
} | ||
// Mutate file descriptor object and store config hash to each file. | ||
// Running lint with different config should invalidate the cache. | ||
if (meta.hashOfConfig !== this._hashOfConfig) { | ||
meta.hashOfConfig = this._hashOfConfig | ||
} | ||
return changed | ||
} | ||
|
||
FileCache.prototype.reconcile = function () { | ||
this._fileCache.reconcile() | ||
} | ||
|
||
FileCache.prototype.destroy = function () { | ||
this._fileCache.destroy() | ||
} | ||
|
||
FileCache.prototype.removeEntry = function (absoluteFilepath) { | ||
this._fileCache.removeEntry(absoluteFilepath) | ||
} | ||
|
||
module.exports = FileCache |
Oops, something went wrong.