diff --git a/lib/checks/mobile/meta-viewport-scale-evaluate.js b/lib/checks/mobile/meta-viewport-scale-evaluate.js
index a5b3170d1e..3ad4eab973 100644
--- a/lib/checks/mobile/meta-viewport-scale-evaluate.js
+++ b/lib/checks/mobile/meta-viewport-scale-evaluate.js
@@ -45,6 +45,18 @@ function metaViewportScaleEvaluate(node, options, virtualNode) {
return false;
}
+ const userScalableAsFloat = parseFloat(result['user-scalable']);
+ if (
+ !lowerBound &&
+ result['user-scalable'] &&
+ (userScalableAsFloat || userScalableAsFloat === 0) &&
+ userScalableAsFloat > -1 &&
+ userScalableAsFloat < 1
+ ) {
+ this.data('user-scalable');
+ return false;
+ }
+
if (
result['maximum-scale'] &&
parseFloat(result['maximum-scale']) < scaleMinimum
diff --git a/test/checks/mobile/meta-viewport-scale.js b/test/checks/mobile/meta-viewport-scale.js
index 332ada1dfc..c1b8e56112 100644
--- a/test/checks/mobile/meta-viewport-scale.js
+++ b/test/checks/mobile/meta-viewport-scale.js
@@ -34,6 +34,30 @@ describe('meta-viewport', function() {
);
});
+ it('should return false on user-scalable in the range <-1, 1>', function() {
+ var vNode = queryFixture(
+ ''
+ );
+
+ assert.isFalse(
+ axe.testUtils
+ .getCheckEvaluate('meta-viewport')
+ .call(checkContext, null, null, vNode)
+ );
+ });
+
+ it('should return false on user-scalable in the range <-1, 1>', function() {
+ var vNode = queryFixture(
+ ''
+ );
+
+ assert.isFalse(
+ axe.testUtils
+ .getCheckEvaluate('meta-viewport')
+ .call(checkContext, null, null, vNode)
+ );
+ });
+
it('should return true on user-scalable=yes', function() {
var vNode = queryFixture(
''
@@ -171,6 +195,30 @@ describe('meta-viewport', function() {
assert.deepEqual(checkContext._data, 'user-scalable=no');
});
+ it('should return false on user-scalable in the range <-1, 1>', function() {
+ var vNode = queryFixture(
+ ''
+ );
+
+ assert.isFalse(
+ axe.testUtils
+ .getCheckEvaluate('meta-viewport')
+ .call(checkContext, null, null, vNode)
+ );
+ });
+
+ it('should return false on user-scalable in the range <-1, 1>', function() {
+ var vNode = queryFixture(
+ ''
+ );
+
+ assert.isFalse(
+ axe.testUtils
+ .getCheckEvaluate('meta-viewport')
+ .call(checkContext, null, null, vNode)
+ );
+ });
+
it('should return true on user-scalable=yes', function() {
var vNode = queryFixture(
''
diff --git a/test/integration/virtual-rules/meta-viewport.js b/test/integration/virtual-rules/meta-viewport.js
index fe0b1bf07d..fd9025795b 100644
--- a/test/integration/virtual-rules/meta-viewport.js
+++ b/test/integration/virtual-rules/meta-viewport.js
@@ -69,6 +69,20 @@ describe('meta-viewport virtual-rule', function() {
assert.lengthOf(results.incomplete, 0);
});
+ it('should fail for user-scalable=0', function() {
+ var results = axe.runVirtualRule('meta-viewport', {
+ nodeName: 'meta',
+ attributes: {
+ name: 'viewport',
+ content: 'user-scalable=0'
+ }
+ });
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
it('should fail for maximum-scale=yes', function() {
var results = axe.runVirtualRule('meta-viewport', {
nodeName: 'meta',