Skip to content

Commit bc4cb8b

Browse files
author
Vladimir Kalmykov
authored
Merge pull request #1 from morulus/feature/tests
Feature/tests
2 parents 13d686a + 730b5f7 commit bc4cb8b

File tree

19 files changed

+527
-75
lines changed

19 files changed

+527
-75
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__tests__

.eslintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"plugins": ["node"],
2+
"plugins": ["node","jest"],
33
"extends": ["eslint:recommended", "plugin:node/recommended"],
44
"rules": {
55
"node/exports-style": ["error", "module.exports"]

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
node_modules
2+
.idea

.npmignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
node_modules
21
.eslintrc.json
2+
.eslintignore
33
.gitignore
4+
test.js
5+
__tests__
6+
__mock__

__mocks__/fs.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* eslint no-undef: 0 */
2+
'use strict';
3+
const path = require('path');
4+
const fs = jest.genMockFromModule('fs');
5+
const root = process.cwd();
6+
let mockFiles = Object.create(null);
7+
8+
function normalize(file) {
9+
return path.relative(root, path.normalize(file));
10+
}
11+
12+
/**
13+
* The path of the files must be relative to root (process.cwd())
14+
*/
15+
function __setMockFiles(newMockFiles) {
16+
mockFiles = Object.create(null);
17+
newMockFiles.forEach(function(file) {
18+
file = path.normalize(file);
19+
const dir = path.dirname(file);
20+
if (!mockFiles[dir]) {
21+
mockFiles[dir] = [];
22+
}
23+
mockFiles[dir].push(path.basename(file));
24+
});
25+
}
26+
27+
function existsSync(file) {
28+
file = normalize(file);
29+
const dir = path.dirname(file);
30+
return Boolean(mockFiles[dir] && mockFiles[dir].includes(path.basename(file)));
31+
}
32+
33+
function stat(file, cb) {
34+
if (existsSync(file)) {
35+
cb(null, {
36+
isFile: function() { return true; }
37+
});
38+
} else {
39+
cb(new Error("Not a file"), null);
40+
}
41+
}
42+
43+
fs.__setMockFiles = __setMockFiles;
44+
fs.existsSync = existsSync;
45+
fs.stat = stat;
46+
fs.readFile = function(file, cb) { cb('body {}'); }
47+
48+
module.exports = fs;

__tests__/postcss-import-sub.test.js

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/* eslint no-undef: 0 */
2+
/* eslint no-console: 0 */
3+
"use strict";
4+
jest.mock('fs');
5+
const fs = require('fs');
6+
const path = require('path');
7+
const root = process.cwd();
8+
9+
jest.mock('postcss-import/lib/resolve-id.js', function() {
10+
const path = require('path');
11+
const resolveEngine = {
12+
resolve: function(id, base, config) {
13+
return Promise.resolve(path.resolve(base, id));
14+
}
15+
}
16+
17+
function resolveId(id, base, config) {
18+
return resolveEngine.resolve(id, base, config);
19+
}
20+
21+
resolveId.setResolver = function(fn) {
22+
resolveEngine.resolve = fn;
23+
}
24+
25+
return resolveId;
26+
});
27+
28+
var sub = require('../index.js').sub;
29+
30+
function mockRender(config) {
31+
return function(id, base, options) {
32+
return Promise.resolve(config.resolve)
33+
.then(function(resolve) {
34+
return resolve(id, path.join(root, base), options||{});
35+
})
36+
.then(function(result) {
37+
if (!(result instanceof Array)) result = [result];
38+
return result.map(function(file) {
39+
return path.relative(root, file);
40+
});
41+
});
42+
}
43+
}
44+
45+
fs.__setMockFiles([
46+
'app/Components/Box/blue.css',
47+
'app/Components/Box/red.css',
48+
'app/Theme/Components/Box/red.css',
49+
]);
50+
51+
describe('postcss-import-sub', () => {
52+
it ('relative `to` substitution', () => {
53+
const render = mockRender(sub([
54+
{
55+
id: new RegExp("red\.css"),
56+
to: "blue.css"
57+
}
58+
]));
59+
return render("red.css", "app/Components/Box/")
60+
.then(function(module) {
61+
expect(module[0]).toBe("app/Components/Box/blue.css");
62+
});
63+
});
64+
65+
it ('relative `to` substitution with dot', () => {
66+
const render = mockRender(sub([
67+
{
68+
id: new RegExp("red\.css"),
69+
to: "./blue.css"
70+
}
71+
]));
72+
return render("red.css", "app/Components/Box/")
73+
.then(function(module) {
74+
expect(module[0]).toBe("app/Components/Box/blue.css");
75+
});
76+
});
77+
78+
it ('absolute `to` substitution', () => {
79+
const render = mockRender(sub([
80+
{
81+
id: new RegExp("red\.css"),
82+
to: "<root>/app/Components/Box/blue.css"
83+
}
84+
]));
85+
return render("red.css", "app/Components/Box/")
86+
.then(function(module) {
87+
expect(module[0]).toBe("app/Components/Box/blue.css");
88+
});
89+
});
90+
91+
it ('relative `path` substitution with dot', () => {
92+
const render = mockRender(sub([
93+
{
94+
id: new RegExp("red\.css"),
95+
path: "<root>/app/Theme/Components/Box/"
96+
}
97+
]));
98+
return render("./red.css", "app/Components/Box/")
99+
.then(function(module) {
100+
expect(module[0]).toBe("app/Theme/Components/Box/red.css");
101+
});
102+
});
103+
104+
it ('relative `path` substitution with without ending slash', () => {
105+
const render = mockRender(sub([
106+
{
107+
id: new RegExp("red\.css"),
108+
path: "<root>/app/Theme/Components/Box"
109+
}
110+
]));
111+
return render("red.css", "app/Components/Box/")
112+
.then(function(module) {
113+
expect(module[0]).toBe("app/Theme/Components/Box/red.css");
114+
});
115+
});
116+
117+
it ('absolute `to` substitution with alias', () => {
118+
const render = mockRender(sub([
119+
{
120+
id: new RegExp("red\.css"),
121+
to: "<root>/app/Theme/Components/Box/<id>"
122+
}
123+
]));
124+
return render("red.css", "app/Components/Box/")
125+
.then(function(module) {
126+
expect(module[0]).toBe("app/Theme/Components/Box/red.css");
127+
});
128+
});
129+
130+
it ('absolute `to` substitution with alias', () => {
131+
const render = mockRender(sub([
132+
{
133+
id: new RegExp("red\.css"),
134+
to: "<root>/app/Theme/Components/Box/<id>"
135+
}
136+
]));
137+
return render("red.css", "app/Components/Box/")
138+
.then(function(module) {
139+
expect(module[0]).toBe("app/Theme/Components/Box/red.css");
140+
});
141+
});
142+
143+
it ('relative `path` with custom aliases', () => {
144+
const render = mockRender(sub([
145+
{
146+
id: new RegExp("red\.css"),
147+
base: /Components\/([a-z0-9]+)\//i,
148+
path: "<root>/app/Theme/Components/<base:$1>/"
149+
}
150+
]));
151+
return render("red.css", "app/Components/Box/")
152+
.then(function(module) {
153+
expect(module[0]).toBe("app/Theme/Components/Box/red.css");
154+
});
155+
});
156+
157+
it ('absolute `to` with custom aliases', () => {
158+
const render = mockRender(sub([
159+
{
160+
id: /([a-z0-9]+)\.css/,
161+
base: /Components\/([a-z0-9]+)\//i,
162+
to: "<root>/app/Theme/Components/<base:$1>/<id:$1>.css"
163+
}
164+
]));
165+
return render("red.css", "app/Components/Box/")
166+
.then(function(module) {
167+
expect(module[0]).toBe("app/Theme/Components/Box/red.css");
168+
});
169+
});
170+
171+
it ('absolute `to` with custom aliases using module', () => {
172+
const render = mockRender(sub([
173+
{
174+
module: /\/([a-z0-9]+)\/([a-z0-9]+)\.css/i,
175+
to: "<root>/app/Theme/Components/<module:$1>/<module:$2>.css"
176+
}
177+
]));
178+
return render("red.css", "app/Components/Box/")
179+
.then(function(module) {
180+
expect(module[0]).toBe("app/Theme/Components/Box/red.css");
181+
});
182+
});
183+
});

examples/colortheme/build.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"use strict";
2+
const gulp = require('gulp');
3+
const express = require('express');
4+
const themeName = process.env.COLOR || 'default';
5+
const chalk = require('chalk');
6+
const launch = require('opn');
7+
const path = require('path');
8+
9+
console.log(chalk.magenta('Build...'));
10+
11+
if (themeName !== 'default') {
12+
console.log(chalk.magenta('Using '+themeName+' theme'));
13+
}
14+
15+
var postcss = require('gulp-postcss');
16+
17+
gulp.src('src/postcss-logo.css')
18+
.pipe( postcss([
19+
require('../../index.js')([
20+
{
21+
base: /src/,
22+
id: /color\.css/,
23+
path: "<root>/themes/"+themeName+"/"
24+
}
25+
]),
26+
require('postcss-simple-vars')
27+
]) )
28+
.pipe( gulp.dest('./build/') )
29+
.on('end', function() {
30+
console.log(chalk.magenta('Completed'));
31+
32+
const app = express();
33+
34+
app.use(express.static('public'));
35+
36+
app.get('/style.css', function (req, res) {
37+
res.sendFile(path.resolve(__dirname, './build/postcss-logo.css'));
38+
})
39+
40+
app.listen(3000);
41+
42+
console.log(chalk.magenta('Open http://localhost:3000/ to see result.'));
43+
launch('http://localhost:3000');
44+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.postCssLogo path {
2+
fill: purple;
3+
}

examples/colortheme/package.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "colortheme",
3+
"version": "1.0.0",
4+
"description": "Switch color themes via postcss-import-sub",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1",
8+
"start": "node build.js"
9+
},
10+
"keywords": [
11+
"postcss",
12+
"postcss-import-sub"
13+
],
14+
"author": "Vladimir Kalmykov <[email protected]>",
15+
"license": "MIT",
16+
"devDependencies": {
17+
"chalk": "^1.1.3",
18+
"express": "^4.14.0",
19+
"gulp": "^3.9.1",
20+
"gulp-postcss": "^6.2.0",
21+
"opn": "^4.0.2",
22+
"postcss-simple-vars": "^3.0.0"
23+
}
24+
}

examples/colortheme/postcss.config.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use strict";
2+
const themeName = process.env.COLOR || 'default';
3+
4+
module.exports = {
5+
plugins: [
6+
require('../../index.js')([
7+
{
8+
base: /src/,
9+
id: /color\.css/,
10+
path: "<root>/themes/"+themeName+"/"
11+
}
12+
]),
13+
require('postcss-simple-vars')
14+
]
15+
}

0 commit comments

Comments
 (0)