diff --git a/src/wappalyzer.js b/src/wappalyzer.js
index a50ddb913..7a2c3e368 100644
--- a/src/wappalyzer.js
+++ b/src/wappalyzer.js
@@ -370,7 +370,7 @@ class Wappalyzer {
attrs.string = attr;
try {
- attrs.regex = new RegExp(attr.replace('/', '\\/'), 'i'); // Escape slashes in regular expression
+ attrs.regex = new RegExp(attr.replace('/', '\/'), 'i'); // Escape slashes in regular expression
} catch (error) {
attrs.regex = new RegExp();
diff --git a/src/wappalyzer.spec.js b/src/wappalyzer.spec.js
index ea68c22e0..f51d7fb10 100644
--- a/src/wappalyzer.spec.js
+++ b/src/wappalyzer.spec.js
@@ -139,5 +139,140 @@ describe('Wappalyzer', () => {
it('should return the version number', () => {
assert.equal(apps.appHtml.version, '1');
});
+
+ it('should analyze html', async () => {
+ const html = `
+
+
+
+ Page title | Html detection
+
+
+
+ Technologies Test Page | Html detection
+
+
+
+
+
+ `;
+ const wappalyzer = new Wappalyzer();
+ wappalyzer.apps = {
+ "Google Tag Manager": {
+ "html": [
+ "googletagmanager\\.com/ns\\.html[^>]+>",
+ ""
+ ]
+ }
+ };
+ var applications = null;
+ wappalyzer.driver = {
+ log () {},
+ displayApps (detectedMap) {
+ applications = detectedMap;
+ }
+ };
+
+ await wappalyzer.analyze({ canonical: 'example.com' }, { html });
+ assert.equal(applications['Google Tag Manager'].name, 'Google Tag Manager');
+ });
+
+ it('should analyze scripts', async () => {
+ const scripts = [
+ 'http://www.google-analytics.com/analytics.js',
+ 'http://example.com/assets/js/jquery.min.js'
+ ];
+ const wappalyzer = new Wappalyzer();
+ wappalyzer.apps = {
+ "Google Analytics": {
+ "cats": [
+ 10
+ ],
+ "script": "google-analytics\\.com\\/(?:ga|urchin|(analytics))\\.js\\;version:\\1?UA:"
+ },
+ "jQuery": {
+ "script": [
+ "jquery(?:\\-|\\.)([\\d.]*\\d)[^/]*\\.js\\;version:\\1",
+ "/([\\d.]+)/jquery(?:\\.min)?\\.js\\;version:\\1",
+ "jquery.*\\.js(?:\\?ver(?:sion)?=([\\d.]+))?\\;version:\\1"
+ ]
+ }
+ };
+ var applications = null;
+ wappalyzer.driver = {
+ log () {},
+ displayApps (detectedMap) {
+ applications = detectedMap;
+ }
+ };
+
+ await wappalyzer.analyze({ canonical: 'example.com' }, { scripts });
+ assert.equal(applications['Google Analytics'].name, 'Google Analytics');
+ assert.equal(applications['jQuery'].name, 'jQuery');
+ });
+
+ it('should analyze headers', async () => {
+ const headers = {
+ 'date': [ 'Thu, 01 Feb 2018 11:34:18 GMT' ],
+ 'connection': [ 'keep-alive' ],
+ 'x-powered-by': [ 'Express'],
+ 'etag': [ 'W/125-1jQLmiya7mfec43xR3Eb3pjdu64s' ],
+ 'content-length': [ '293' ],
+ 'content-type': [ 'text/html; charset=utf-8' ]
+ };
+ const wappalyzer = new Wappalyzer();
+ wappalyzer.apps = {
+ "Express": {
+ "headers": {
+ "X-Powered-By": "^Express$"
+ }
+ }
+ };
+ var applications = null;
+ wappalyzer.driver = {
+ log () {},
+ displayApps (detectedMap) {
+ applications = detectedMap;
+ }
+ };
+
+ await wappalyzer.analyze({ canonical: 'example.com' }, { headers });
+ assert.equal(applications['Express'].name, 'Express');
+ });
+
+ it('should analyze js globals', async () => {
+ const js = {
+ 'Moment.js': { 'moment': { '0': true } },
+ 'Google Font API': { 'WebFonts': { '0': true } }
+ };
+ const wappalyzer = new Wappalyzer();
+ wappalyzer.apps = {
+ "Moment.js": {
+ "js": {
+ "moment": "",
+ "moment.version": "(.*)\\;version:\\1"
+ }
+ },
+ "Google Font API": {
+ "js": {
+ "WebFonts": ""
+ }
+ }
+ };
+ var applications = null;
+ wappalyzer.driver = {
+ log () {},
+ displayApps (detectedMap) {
+ applications = detectedMap;
+ }
+ };
+
+ wappalyzer.parseJsPatterns();
+ await wappalyzer.analyze({ canonical: 'example.com' }, { js });
+
+ assert.equal(applications['Google Font API'].name, 'Google Font API');
+ assert.equal(applications['Moment.js'].name, 'Moment.js');
+ });
});
});